pacemaker  3.0.0-d8340737c4
Scalable High-Availability cluster resource manager
ipc_controld.c
Go to the documentation of this file.
1 /*
2  * Copyright 2020-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 Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #include <errno.h>
13 #include <inttypes.h> // PRIu32
14 #include <stdbool.h>
15 #include <stdint.h> // uint32_t
16 #include <stdio.h>
17 
18 #include <libxml/tree.h>
19 
20 #include <crm/crm.h>
21 #include <crm/common/xml.h>
22 #include <crm/common/ipc.h>
25 #include "crmcommon_private.h"
26 
27 struct controld_api_private_s {
28  char *client_uuid;
29  unsigned int replies_expected;
30 };
31 
32 static xmlNode *create_hello_message(const char *uuid, const char *client_name,
33  const char *major_version,
34  const char *minor_version);
35 
44 const char *
46 {
47  switch (reply) {
49  return "reprobe";
51  return "info";
53  return "resource";
55  return "ping";
57  return "nodes";
58  default:
59  return "unknown";
60  }
61 }
62 
63 // \return Standard Pacemaker return code
64 static int
65 new_data(pcmk_ipc_api_t *api)
66 {
67  struct controld_api_private_s *private = NULL;
68 
69  api->api_data = calloc(1, sizeof(struct controld_api_private_s));
70 
71  if (api->api_data == NULL) {
72  return errno;
73  }
74 
75  private = api->api_data;
76 
77  /* This is set to the PID because that's how it was always done, but PIDs
78  * are not unique because clients can be remote. The value appears to be
79  * unused other than as part of PCMK__XA_CRM_SYS_FROM in IPC requests, which
80  * is only compared against the internal system names (CRM_SYSTEM_TENGINE,
81  * etc.), so it shouldn't be a problem.
82  */
83  private->client_uuid = pcmk__getpid_s();
84 
85  /* @TODO Implement a call ID model similar to the CIB, executor, and fencer
86  * IPC APIs, so that requests and replies can be matched, and
87  * duplicate replies can be discarded.
88  */
89  return pcmk_rc_ok;
90 }
91 
92 static void
93 free_data(void *data)
94 {
95  free(((struct controld_api_private_s *) data)->client_uuid);
96  free(data);
97 }
98 
99 // \return Standard Pacemaker return code
100 static int
101 post_connect(pcmk_ipc_api_t *api)
102 {
103  /* The controller currently requires clients to register via a hello
104  * request, but does not reply back.
105  */
106  struct controld_api_private_s *private = api->api_data;
107  const char *client_name = crm_system_name? crm_system_name : "client";
108  xmlNode *hello;
109  int rc;
110 
111  hello = create_hello_message(private->client_uuid, client_name,
114  rc = pcmk__send_ipc_request(api, hello);
115  pcmk__xml_free(hello);
116  if (rc != pcmk_rc_ok) {
117  crm_info("Could not send IPC hello to %s: %s " QB_XS " rc=%s",
118  pcmk_ipc_name(api, true), pcmk_rc_str(rc), rc);
119  } else {
120  crm_debug("Sent IPC hello to %s", pcmk_ipc_name(api, true));
121  }
122  return rc;
123 }
124 
125 static void
126 set_node_info_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
127 {
128  data->reply_type = pcmk_controld_reply_info;
129  if (msg_data == NULL) {
130  return;
131  }
132  data->data.node_info.have_quorum =
134  data->data.node_info.is_remote =
136 
137  /* Integer node_info.id is currently valid only for Corosync nodes.
138  *
139  * @TODO: Improve handling after pcmk__node_status_t is refactored to handle
140  * layer-specific data better.
141  */
142  crm_element_value_int(msg_data, PCMK_XA_ID, &(data->data.node_info.id));
143 
144  data->data.node_info.uuid = crm_element_value(msg_data, PCMK_XA_ID);
145  data->data.node_info.uname = crm_element_value(msg_data, PCMK_XA_UNAME);
146  data->data.node_info.state = crm_element_value(msg_data, PCMK_XA_CRMD);
147 }
148 
149 static void
150 set_ping_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
151 {
152  data->reply_type = pcmk_controld_reply_ping;
153  if (msg_data == NULL) {
154  return;
155  }
156  data->data.ping.sys_from = crm_element_value(msg_data,
158  data->data.ping.fsa_state = crm_element_value(msg_data,
160  data->data.ping.result = crm_element_value(msg_data, PCMK_XA_RESULT);
161 }
162 
163 static void
164 set_nodes_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
165 {
166  pcmk_controld_api_node_t *node_info;
167 
168  data->reply_type = pcmk_controld_reply_nodes;
169  for (xmlNode *node = pcmk__xe_first_child(msg_data, PCMK_XE_NODE, NULL,
170  NULL);
171  node != NULL; node = pcmk__xe_next(node, PCMK_XE_NODE)) {
172 
173  long long id_ll = 0;
174 
175  node_info = pcmk__assert_alloc(1, sizeof(pcmk_controld_api_node_t));
176  crm_element_value_ll(node, PCMK_XA_ID, &id_ll);
177  if (id_ll > 0) {
178  node_info->id = id_ll;
179  }
180  node_info->uname = crm_element_value(node, PCMK_XA_UNAME);
181  node_info->state = crm_element_value(node, PCMK__XA_IN_CCM);
182  data->data.nodes = g_list_prepend(data->data.nodes, node_info);
183  }
184 }
185 
186 static bool
187 reply_expected(pcmk_ipc_api_t *api, const xmlNode *request)
188 {
189  // We only need to handle commands that API functions can send
195  CRM_OP_PING,
198  NULL);
199 }
200 
201 static bool
202 dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
203 {
204  struct controld_api_private_s *private = api->api_data;
205  crm_exit_t status = CRM_EX_OK;
206  xmlNode *wrapper = NULL;
207  xmlNode *msg_data = NULL;
208  const char *value = NULL;
209  pcmk_controld_api_reply_t reply_data = {
210  pcmk_controld_reply_unknown, NULL, NULL,
211  };
212 
213  if (pcmk__xe_is(reply, PCMK__XE_ACK)) {
214  /* ACKs are trivial responses that do not count toward expected replies,
215  * and do not have all the fields that validation requires, so skip that
216  * processing.
217  */
218  return private->replies_expected > 0;
219  }
220 
221  if (private->replies_expected > 0) {
222  private->replies_expected--;
223  }
224 
225  // Do some basic validation of the reply
226 
227  value = crm_element_value(reply, PCMK__XA_SUBT);
228  if (pcmk__str_eq(value, PCMK__VALUE_REQUEST, pcmk__str_none)) {
229  /* @COMPAT Controllers <3.0.0 set PCMK__XA_SUBT to PCMK__VALUE_REQUEST
230  * for certain replies. Once we no longer support Pacemaker Remote nodes
231  * connecting to cluster nodes <3.0.0, or rolling upgrades from <3.0.0,
232  * we can drop this check.
233  */
234  crm_trace("Received a reply that was marked as a request "
235  "(bug unless sent by a controller <3.0.0)");
236 
237  } else if (!pcmk__str_eq(value, PCMK__VALUE_RESPONSE, pcmk__str_none)) {
238  crm_info("Unrecognizable message from controller: "
239  "invalid message type '%s'", pcmk__s(value, ""));
240  status = CRM_EX_PROTOCOL;
241  goto done;
242  }
243 
244  if (pcmk__str_empty(crm_element_value(reply, PCMK_XA_REFERENCE))) {
245  crm_info("Unrecognizable message from controller: no reference");
246  status = CRM_EX_PROTOCOL;
247  goto done;
248  }
249 
250  value = crm_element_value(reply, PCMK__XA_CRM_TASK);
251  if (pcmk__str_empty(value)) {
252  crm_info("Unrecognizable message from controller: no command name");
253  status = CRM_EX_PROTOCOL;
254  goto done;
255  }
256 
257  // Parse useful info from reply
258 
259  reply_data.feature_set = crm_element_value(reply, PCMK_XA_VERSION);
260  reply_data.host_from = crm_element_value(reply, PCMK__XA_SRC);
261 
262  wrapper = pcmk__xe_first_child(reply, PCMK__XE_CRM_XML, NULL, NULL);
263  msg_data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
264 
265  if (!strcmp(value, CRM_OP_REPROBE)) {
267 
268  } else if (!strcmp(value, CRM_OP_NODE_INFO)) {
269  set_node_info_data(&reply_data, msg_data);
270 
271  } else if (!strcmp(value, CRM_OP_INVOKE_LRM)) {
273  reply_data.data.resource.node_state = msg_data;
274 
275  } else if (!strcmp(value, CRM_OP_PING)) {
276  set_ping_data(&reply_data, msg_data);
277 
278  } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
279  set_nodes_data(&reply_data, msg_data);
280 
281  } else {
282  crm_info("Unrecognizable message from controller: unknown command '%s'",
283  value);
284  status = CRM_EX_PROTOCOL;
285  }
286 
287 done:
288  pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
289 
290  // Free any reply data that was allocated
291  if (pcmk__str_eq(value, PCMK__CONTROLD_CMD_NODES, pcmk__str_casei)) {
292  g_list_free_full(reply_data.data.nodes, free);
293  }
294 
295  return false; // No further replies needed
296 }
297 
300 {
301  pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
302 
303  if (cmds != NULL) {
304  cmds->new_data = new_data;
305  cmds->free_data = free_data;
306  cmds->post_connect = post_connect;
307  cmds->reply_expected = reply_expected;
308  cmds->dispatch = dispatch;
309  }
310  return cmds;
311 }
312 
324 static xmlNode *
325 create_controller_request(const pcmk_ipc_api_t *api, const char *op,
326  const char *node, xmlNode *msg_data)
327 {
328  struct controld_api_private_s *private = NULL;
329  const char *sys_to = NULL;
330  char *sender_system = NULL;
331  xmlNode *request = NULL;
332 
333  if (api == NULL) {
334  return NULL;
335  }
336  private = api->api_data;
337  if ((node == NULL) && !strcmp(op, CRM_OP_PING)) {
338  sys_to = CRM_SYSTEM_DC;
339  } else {
340  sys_to = CRM_SYSTEM_CRMD;
341  }
342  sender_system = crm_strdup_printf("%s_%s", private->client_uuid,
343  pcmk__s(crm_system_name, "client"));
344  request = pcmk__new_request(pcmk_ipc_controld, sender_system, node, sys_to,
345  op, msg_data);
346  free(sender_system);
347  return request;
348 }
349 
350 // \return Standard Pacemaker return code
351 static int
352 send_controller_request(pcmk_ipc_api_t *api, const xmlNode *request,
353  bool reply_is_expected)
354 {
355  if (crm_element_value(request, PCMK_XA_REFERENCE) == NULL) {
356  return EINVAL;
357  }
358  if (reply_is_expected) {
359  struct controld_api_private_s *private = api->api_data;
360 
361  private->replies_expected++;
362  }
363  return pcmk__send_ipc_request(api, request);
364 }
365 
366 static xmlNode *
367 create_reprobe_message_data(const char *target_node, const char *router_node)
368 {
369  xmlNode *msg_data;
370 
371  msg_data = pcmk__xe_create(NULL, "data_for_" CRM_OP_REPROBE);
372  crm_xml_add(msg_data, PCMK__META_ON_NODE, target_node);
373  if ((router_node != NULL) && !pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
374  crm_xml_add(msg_data, PCMK__XA_ROUTER_NODE, router_node);
375  }
376  return msg_data;
377 }
378 
389 int
390 pcmk_controld_api_reprobe(pcmk_ipc_api_t *api, const char *target_node,
391  const char *router_node)
392 {
393  xmlNode *request;
394  xmlNode *msg_data;
395  int rc = pcmk_rc_ok;
396 
397  if (api == NULL) {
398  return EINVAL;
399  }
400  if (router_node == NULL) {
401  router_node = target_node;
402  }
403  crm_debug("Sending %s IPC request to reprobe %s via %s",
404  pcmk_ipc_name(api, true), pcmk__s(target_node, "local node"),
405  pcmk__s(router_node, "local node"));
406  msg_data = create_reprobe_message_data(target_node, router_node);
407  request = create_controller_request(api, CRM_OP_REPROBE, router_node,
408  msg_data);
409  rc = send_controller_request(api, request, true);
410  pcmk__xml_free(msg_data);
411  pcmk__xml_free(request);
412  return rc;
413 }
414 
424 int
426 {
427  xmlNode *request;
428  int rc = pcmk_rc_ok;
429 
430  request = create_controller_request(api, CRM_OP_NODE_INFO, NULL, NULL);
431  if (request == NULL) {
432  return EINVAL;
433  }
434  if (nodeid > 0) {
435  crm_xml_add_ll(request, PCMK_XA_ID, nodeid);
436  }
437 
438  rc = send_controller_request(api, request, true);
439  pcmk__xml_free(request);
440  return rc;
441 }
442 
452 int
453 pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
454 {
455  xmlNode *request;
456  int rc = pcmk_rc_ok;
457 
458  request = create_controller_request(api, CRM_OP_PING, node_name, NULL);
459  if (request == NULL) {
460  return EINVAL;
461  }
462  rc = send_controller_request(api, request, true);
463  pcmk__xml_free(request);
464  return rc;
465 }
466 
475 int
477 {
478  xmlNode *request;
479  int rc = EINVAL;
480 
481  request = create_controller_request(api, PCMK__CONTROLD_CMD_NODES, NULL,
482  NULL);
483  if (request != NULL) {
484  rc = send_controller_request(api, request, true);
485  pcmk__xml_free(request);
486  }
487  return rc;
488 }
489 
490 // \return Standard Pacemaker return code
491 static int
492 controller_resource_op(pcmk_ipc_api_t *api, const char *op,
493  const char *target_node, const char *router_node,
494  bool cib_only, const char *rsc_id,
495  const char *rsc_long_id, const char *standard,
496  const char *provider, const char *type)
497 {
498  int rc = pcmk_rc_ok;
499  char *key;
500  xmlNode *request, *msg_data, *xml_rsc, *params;
501 
502  if (api == NULL) {
503  return EINVAL;
504  }
505  if (router_node == NULL) {
506  router_node = target_node;
507  }
508 
509  msg_data = pcmk__xe_create(NULL, PCMK__XE_RSC_OP);
510 
511  /* The controller logs the transition key from resource op requests, so we
512  * need to have *something* for it.
513  * @TODO don't use "crm-resource"
514  */
515  key = pcmk__transition_key(0, getpid(), 0,
516  "xxxxxxxx-xrsc-opxx-xcrm-resourcexxxx");
517  crm_xml_add(msg_data, PCMK__XA_TRANSITION_KEY, key);
518  free(key);
519 
520  crm_xml_add(msg_data, PCMK__META_ON_NODE, target_node);
521  if (!pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
522  crm_xml_add(msg_data, PCMK__XA_ROUTER_NODE, router_node);
523  }
524 
525  if (cib_only) {
526  // Indicate that only the CIB needs to be cleaned
528  }
529 
530  xml_rsc = pcmk__xe_create(msg_data, PCMK_XE_PRIMITIVE);
531  crm_xml_add(xml_rsc, PCMK_XA_ID, rsc_id);
532  crm_xml_add(xml_rsc, PCMK__XA_LONG_ID, rsc_long_id);
533  crm_xml_add(xml_rsc, PCMK_XA_CLASS, standard);
534  crm_xml_add(xml_rsc, PCMK_XA_PROVIDER, provider);
535  crm_xml_add(xml_rsc, PCMK_XA_TYPE, type);
536 
537  params = pcmk__xe_create(msg_data, PCMK__XE_ATTRIBUTES);
539 
540  // The controller parses the timeout from the request
542  crm_xml_add(params, key, "60000"); /* 1 minute */ //@TODO pass as arg
543  free(key);
544 
545  request = create_controller_request(api, op, router_node, msg_data);
546  rc = send_controller_request(api, request, true);
547  pcmk__xml_free(msg_data);
548  pcmk__xml_free(request);
549  return rc;
550 }
551 
567 int
569  const char *target_node, const char *router_node,
570  const char *rsc_id, const char *rsc_long_id,
571  const char *standard, const char *provider,
572  const char *type)
573 {
574  crm_debug("Sending %s IPC request to fail %s (a.k.a. %s) on %s via %s",
575  pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
576  pcmk__s(rsc_long_id, "no other names"),
577  pcmk__s(target_node, "unspecified node"),
578  pcmk__s(router_node, "unspecified node"));
579  return controller_resource_op(api, CRM_OP_LRM_FAIL, target_node,
580  router_node, false, rsc_id, rsc_long_id,
581  standard, provider, type);
582 }
583 
600 int
601 pcmk_controld_api_refresh(pcmk_ipc_api_t *api, const char *target_node,
602  const char *router_node,
603  const char *rsc_id, const char *rsc_long_id,
604  const char *standard, const char *provider,
605  const char *type, bool cib_only)
606 {
607  crm_debug("Sending %s IPC request to refresh %s (a.k.a. %s) on %s via %s",
608  pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
609  pcmk__s(rsc_long_id, "no other names"),
610  pcmk__s(target_node, "unspecified node"),
611  pcmk__s(router_node, "unspecified node"));
612  return controller_resource_op(api, CRM_OP_LRM_DELETE, target_node,
613  router_node, cib_only, rsc_id, rsc_long_id,
614  standard, provider, type);
615 }
616 
624 unsigned int
626 {
627  struct controld_api_private_s *private = api->api_data;
628 
629  return private->replies_expected;
630 }
631 
636 static xmlNode *
637 create_hello_message(const char *uuid, const char *client_name,
638  const char *major_version, const char *minor_version)
639 {
640  xmlNode *hello_node = NULL;
641  xmlNode *hello = NULL;
642  char *sender_system = NULL;
643 
644  if (pcmk__str_empty(uuid) || pcmk__str_empty(client_name)
645  || pcmk__str_empty(major_version) || pcmk__str_empty(minor_version)) {
646  crm_err("Could not create IPC hello message from %s (UUID %s): "
647  "missing information",
648  client_name? client_name : "unknown client",
649  uuid? uuid : "unknown");
650  return NULL;
651  }
652 
653  hello_node = pcmk__xe_create(NULL, PCMK__XE_OPTIONS);
654  crm_xml_add(hello_node, PCMK__XA_MAJOR_VERSION, major_version);
655  crm_xml_add(hello_node, PCMK__XA_MINOR_VERSION, minor_version);
656  crm_xml_add(hello_node, PCMK__XA_CLIENT_NAME, client_name);
657 
658  // @TODO Nothing uses this. Drop, or keep for debugging?
659  crm_xml_add(hello_node, PCMK__XA_CLIENT_UUID, uuid);
660 
661  sender_system = crm_strdup_printf("%s_%s", uuid, client_name);
662  hello = pcmk__new_request(pcmk_ipc_controld, sender_system, NULL, NULL,
663  CRM_OP_HELLO, hello_node);
664  free(sender_system);
665  pcmk__xml_free(hello_node);
666  if (hello == NULL) {
667  crm_err("Could not create IPC hello message from %s (UUID %s): "
668  "Request creation failed", client_name, uuid);
669  return NULL;
670  }
671 
672  crm_trace("Created hello message from %s (UUID %s)", client_name, uuid);
673  return hello;
674 }
A dumping ground.
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__VALUE_RESPONSE
union pcmk_controld_api_reply_t::@1 data
int crm_element_value_ll(const xmlNode *data, const char *name, long long *dest)
Retrieve the long long integer value of an XML attribute.
Definition: xml_element.c:1291
char data[0]
Definition: cpg.c:58
enum pcmk_controld_api_reply reply_type
Definition: ipc_controld.h:59
#define PCMK__XA_ROUTER_NODE
#define PCMK_XA_REMOTE_NODE
Definition: xml_names.h:376
int pcmk_controld_api_reprobe(pcmk_ipc_api_t *api, const char *target_node, const char *router_node)
Send a reprobe controller operation.
Definition: ipc_controld.c:390
enum pcmk_ipc_server type
Definition: cpg.c:51
const char * host_from
Name of node that sent reply.
Definition: ipc_controld.h:61
#define PCMK_XE_PRIMITIVE
Definition: xml_names.h:164
#define CRM_OP_REPROBE
Definition: crm.h:128
#define PCMK__CONTROLD_API_MAJOR
#define CRM_FEATURE_SET
Definition: crm.h:66
#define PCMK_XA_REFERENCE
Definition: xml_names.h:372
#define PCMK_XA_HAVE_QUORUM
Definition: xml_names.h:295
#define PCMK__XA_MODE
#define PCMK__XE_ATTRIBUTES
#define PCMK_XA_PROVIDER
Definition: xml_names.h:364
char * crm_system_name
Definition: utils.c:44
enum crm_exit_e crm_exit_t
#define PCMK__XA_MAJOR_VERSION
#define PCMK__XA_SUBT
#define PCMK__META_ON_NODE
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition: xml_element.c:1538
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:609
#define PCMK_XA_TYPE
Definition: xml_names.h:430
G_GNUC_INTERNAL void pcmk__call_ipc_callback(pcmk_ipc_api_t *api, enum pcmk_ipc_event event_type, crm_exit_t status, void *event_data)
Definition: ipc_client.c:150
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition: xml_element.c:407
#define CRM_OP_LRM_FAIL
Definition: crm.h:126
#define CRM_SYSTEM_DC
Definition: crm.h:81
#define PCMK__XA_CRMD_STATE
const char * crm_xml_add_ll(xmlNode *node, const char *name, long long value)
Create an XML attribute with specified name and long long int value.
Definition: xml_element.c:1120
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
#define PCMK__XA_CRM_TASK
#define PCMK__CONTROLD_API_MINOR
#define PCMK__XA_TRANSITION_KEY
char * pcmk__transition_key(int transition_id, int action_id, int target_rc, const char *node)
Definition: actions.c:402
Protocol violated.
Definition: results.h:257
#define crm_debug(fmt, args...)
Definition: logging.h:370
struct pcmk_controld_api_reply_t::@1::@3 resource
#define PCMK_XA_UNAME
Definition: xml_names.h:431
G_GNUC_INTERNAL int pcmk__send_ipc_request(pcmk_ipc_api_t *api, const xmlNode *request)
Definition: ipc_client.c:658
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: xml_element.c:1168
#define crm_trace(fmt, args...)
Definition: logging.h:372
const char * feature_set
CRM feature set advertised by controller.
Definition: ipc_controld.h:60
#define PCMK__VALUE_CIB
pcmk__ipc_methods_t * pcmk__controld_api_methods(void)
Definition: ipc_controld.c:299
Wrappers for and extensions to libxml2.
int pcmk_controld_api_refresh(pcmk_ipc_api_t *api, const char *target_node, const char *router_node, const char *rsc_id, const char *rsc_long_id, const char *standard, const char *provider, const char *type, bool cib_only)
Ask the controller to refresh a resource.
Definition: ipc_controld.c:601
#define PCMK__XA_CLIENT_UUID
#define pcmk__new_request(server, sender_system, recipient_node, recipient_system, task, data)
#define PCMK__XE_RSC_OP
#define PCMK_XA_ID
Definition: xml_names.h:301
Success.
Definition: results.h:231
#define PCMK__XE_OPTIONS
int(* post_connect)(pcmk_ipc_api_t *api)
#define PCMK__XA_CRM_SUBSYSTEM
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:1051
IPC commands for Pacemaker controller.
#define PCMK_META_TIMEOUT
Definition: options.h:114
int pcmk_controld_api_list_nodes(pcmk_ipc_api_t *api)
Ask the controller for cluster information.
Definition: ipc_controld.c:476
#define CRM_SYSTEM_CRMD
Definition: crm.h:84
xmlNode * pcmk__xe_next(const xmlNode *node, const char *element_name)
Definition: xml_element.c:106
#define PCMK__XA_LONG_ID
#define PCMK_XA_CRM_FEATURE_SET
Definition: xml_names.h:254
int(* new_data)(pcmk_ipc_api_t *api)
#define CRM_OP_RM_NODE_CACHE
Definition: crm.h:131
#define PCMK__XA_MINOR_VERSION
int pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
Send a "node info" controller operation.
Definition: ipc_controld.c:425
#define PCMK__XE_CRM_XML
#define PCMK_XA_CLASS
Definition: xml_names.h:246
#define PCMK_XE_NODE
Definition: xml_names.h:136
bool(* dispatch)(pcmk_ipc_api_t *api, xmlNode *msg)
bool(* reply_expected)(pcmk_ipc_api_t *api, const xmlNode *request)
Controller.
Definition: ipc.h:52
int pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
Ask the controller for status.
Definition: ipc_controld.c:453
#define CRM_OP_HELLO
Definition: crm.h:117
#define crm_err(fmt, args...)
Definition: logging.h:359
#define PCMK_XA_CRMD
Definition: xml_names.h:256
#define PCMK__XE_ACK
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
void(* free_data)(void *api_data)
const char * pcmk_ipc_name(const pcmk_ipc_api_t *api, bool for_log)
Get the IPC name used with an IPC API connection.
Definition: ipc_client.c:247
#define PCMK__XA_IN_CCM
unsigned int pcmk_controld_api_replies_expected(const pcmk_ipc_api_t *api)
Get the number of IPC replies currently expected from the controller.
Definition: ipc_controld.c:625
#define CRM_OP_INVOKE_LRM
Definition: crm.h:124
const char * pcmk__controld_api_reply2str(enum pcmk_controld_api_reply reply)
Definition: ipc_controld.c:45
IPC interface to Pacemaker daemons.
#define CRM_OP_NODE_INFO
Definition: crm.h:113
#define PCMK__CONTROLD_CMD_NODES
Definition: crm_internal.h:90
#define CRM_OP_PING
Definition: crm.h:112
Daemon&#39;s reply to client IPC request.
Definition: ipc.h:68
#define pcmk__assert_alloc(nmemb, size)
Definition: internal.h:257
#define CRM_OP_LRM_DELETE
Definition: crm.h:125
#define PCMK_XA_RESULT
Definition: xml_names.h:386
#define PCMK__VALUE_REQUEST
#define crm_info(fmt, args...)
Definition: logging.h:367
int pcmk_controld_api_fail(pcmk_ipc_api_t *api, const char *target_node, const char *router_node, const char *rsc_id, const char *rsc_long_id, const char *standard, const char *provider, const char *type)
Ask the controller to fail a resource.
Definition: ipc_controld.c:568
#define PCMK__XA_SRC
#define PCMK__XA_CLIENT_NAME
#define PCMK_XA_VERSION
Definition: xml_names.h:444
pcmk_controld_api_reply
Possible types of controller replies.
Definition: ipc_controld.h:31
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
char * crm_meta_name(const char *field)
Get the environment variable equivalent of a meta-attribute name.
Definition: nvpair.c:407