pacemaker  2.1.8-3980678f03
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 
40 const char *
42 {
43  switch (reply) {
45  return "reprobe";
47  return "info";
49  return "resource";
51  return "ping";
53  return "nodes";
54  default:
55  return "unknown";
56  }
57 }
58 
59 // \return Standard Pacemaker return code
60 static int
61 new_data(pcmk_ipc_api_t *api)
62 {
63  struct controld_api_private_s *private = NULL;
64 
65  api->api_data = calloc(1, sizeof(struct controld_api_private_s));
66 
67  if (api->api_data == NULL) {
68  return errno;
69  }
70 
71  private = api->api_data;
72 
73  /* This is set to the PID because that's how it was always done, but PIDs
74  * are not unique because clients can be remote. The value appears to be
75  * unused other than as part of PCMK__XA_CRM_SYS_FROM in IPC requests, which
76  * is only compared against the internal system names (CRM_SYSTEM_TENGINE,
77  * etc.), so it shouldn't be a problem.
78  */
79  private->client_uuid = pcmk__getpid_s();
80 
81  /* @TODO Implement a call ID model similar to the CIB, executor, and fencer
82  * IPC APIs, so that requests and replies can be matched, and
83  * duplicate replies can be discarded.
84  */
85  return pcmk_rc_ok;
86 }
87 
88 static void
89 free_data(void *data)
90 {
91  free(((struct controld_api_private_s *) data)->client_uuid);
92  free(data);
93 }
94 
95 // \return Standard Pacemaker return code
96 static int
97 post_connect(pcmk_ipc_api_t *api)
98 {
99  /* The controller currently requires clients to register via a hello
100  * request, but does not reply back.
101  */
102  struct controld_api_private_s *private = api->api_data;
103  const char *client_name = crm_system_name? crm_system_name : "client";
104  xmlNode *hello;
105  int rc;
106 
107  hello = create_hello_message(private->client_uuid, client_name,
110  rc = pcmk__send_ipc_request(api, hello);
111  free_xml(hello);
112  if (rc != pcmk_rc_ok) {
113  crm_info("Could not send IPC hello to %s: %s " CRM_XS " rc=%s",
114  pcmk_ipc_name(api, true), pcmk_rc_str(rc), rc);
115  } else {
116  crm_debug("Sent IPC hello to %s", pcmk_ipc_name(api, true));
117  }
118  return rc;
119 }
120 
121 static void
122 set_node_info_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
123 {
124  data->reply_type = pcmk_controld_reply_info;
125  if (msg_data == NULL) {
126  return;
127  }
128  data->data.node_info.have_quorum =
130  data->data.node_info.is_remote =
132 
133  /* Integer node_info.id is currently valid only for Corosync nodes.
134  *
135  * @TODO: Improve handling after crm_node_t is refactored to handle layer-
136  * specific data better.
137  */
138  crm_element_value_int(msg_data, PCMK_XA_ID, &(data->data.node_info.id));
139 
140  data->data.node_info.uuid = crm_element_value(msg_data, PCMK_XA_ID);
141  data->data.node_info.uname = crm_element_value(msg_data, PCMK_XA_UNAME);
142  data->data.node_info.state = crm_element_value(msg_data, PCMK_XA_CRMD);
143 }
144 
145 static void
146 set_ping_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
147 {
148  data->reply_type = pcmk_controld_reply_ping;
149  if (msg_data == NULL) {
150  return;
151  }
152  data->data.ping.sys_from = crm_element_value(msg_data,
154  data->data.ping.fsa_state = crm_element_value(msg_data,
156  data->data.ping.result = crm_element_value(msg_data, PCMK_XA_RESULT);
157 }
158 
159 static void
160 set_nodes_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
161 {
162  pcmk_controld_api_node_t *node_info;
163 
164  data->reply_type = pcmk_controld_reply_nodes;
165  for (xmlNode *node = pcmk__xe_first_child(msg_data, PCMK_XE_NODE, NULL,
166  NULL);
167  node != NULL; node = pcmk__xe_next_same(node)) {
168 
169  long long id_ll = 0;
170 
171  node_info = pcmk__assert_alloc(1, sizeof(pcmk_controld_api_node_t));
172  crm_element_value_ll(node, PCMK_XA_ID, &id_ll);
173  if (id_ll > 0) {
174  node_info->id = id_ll;
175  }
176  node_info->uname = crm_element_value(node, PCMK_XA_UNAME);
177  node_info->state = crm_element_value(node, PCMK__XA_IN_CCM);
178  data->data.nodes = g_list_prepend(data->data.nodes, node_info);
179  }
180 }
181 
182 static bool
183 reply_expected(pcmk_ipc_api_t *api, const xmlNode *request)
184 {
185  // We only need to handle commands that API functions can send
191  CRM_OP_PING,
194  NULL);
195 }
196 
197 static bool
198 dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
199 {
200  struct controld_api_private_s *private = api->api_data;
201  crm_exit_t status = CRM_EX_OK;
202  xmlNode *wrapper = NULL;
203  xmlNode *msg_data = NULL;
204  const char *value = NULL;
205  pcmk_controld_api_reply_t reply_data = {
206  pcmk_controld_reply_unknown, NULL, NULL,
207  };
208 
209  if (pcmk__xe_is(reply, PCMK__XE_ACK)) {
210  /* ACKs are trivial responses that do not count toward expected replies,
211  * and do not have all the fields that validation requires, so skip that
212  * processing.
213  */
214  return private->replies_expected > 0;
215  }
216 
217  if (private->replies_expected > 0) {
218  private->replies_expected--;
219  }
220 
221  // Do some basic validation of the reply
222 
223  /* @TODO We should be able to verify that value is always a response, but
224  * currently the controller doesn't always properly set the type. Even
225  * if we fix the controller, we'll still need to handle replies from
226  * old versions (feature set could be used to differentiate).
227  */
228  value = crm_element_value(reply, PCMK__XA_SUBT);
230  NULL)) {
231  crm_info("Unrecognizable message from controller: "
232  "invalid message type '%s'", pcmk__s(value, ""));
233  status = CRM_EX_PROTOCOL;
234  goto done;
235  }
236 
237  if (pcmk__str_empty(crm_element_value(reply, PCMK_XA_REFERENCE))) {
238  crm_info("Unrecognizable message from controller: no reference");
239  status = CRM_EX_PROTOCOL;
240  goto done;
241  }
242 
243  value = crm_element_value(reply, PCMK__XA_CRM_TASK);
244  if (pcmk__str_empty(value)) {
245  crm_info("Unrecognizable message from controller: no command name");
246  status = CRM_EX_PROTOCOL;
247  goto done;
248  }
249 
250  // Parse useful info from reply
251 
252  reply_data.feature_set = crm_element_value(reply, PCMK_XA_VERSION);
253  reply_data.host_from = crm_element_value(reply, PCMK__XA_SRC);
254 
255  wrapper = pcmk__xe_first_child(reply, PCMK__XE_CRM_XML, NULL, NULL);
256  msg_data = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
257 
258  if (!strcmp(value, CRM_OP_REPROBE)) {
260 
261  } else if (!strcmp(value, CRM_OP_NODE_INFO)) {
262  set_node_info_data(&reply_data, msg_data);
263 
264  } else if (!strcmp(value, CRM_OP_INVOKE_LRM)) {
266  reply_data.data.resource.node_state = msg_data;
267 
268  } else if (!strcmp(value, CRM_OP_PING)) {
269  set_ping_data(&reply_data, msg_data);
270 
271  } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
272  set_nodes_data(&reply_data, msg_data);
273 
274  } else {
275  crm_info("Unrecognizable message from controller: unknown command '%s'",
276  value);
277  status = CRM_EX_PROTOCOL;
278  }
279 
280 done:
281  pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
282 
283  // Free any reply data that was allocated
284  if (pcmk__str_eq(value, PCMK__CONTROLD_CMD_NODES, pcmk__str_casei)) {
285  g_list_free_full(reply_data.data.nodes, free);
286  }
287 
288  return false; // No further replies needed
289 }
290 
293 {
294  pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
295 
296  if (cmds != NULL) {
297  cmds->new_data = new_data;
298  cmds->free_data = free_data;
299  cmds->post_connect = post_connect;
300  cmds->reply_expected = reply_expected;
301  cmds->dispatch = dispatch;
302  }
303  return cmds;
304 }
305 
317 static xmlNode *
318 create_controller_request(const pcmk_ipc_api_t *api, const char *op,
319  const char *node, xmlNode *msg_data)
320 {
321  struct controld_api_private_s *private = NULL;
322  const char *sys_to = NULL;
323 
324  if (api == NULL) {
325  return NULL;
326  }
327  private = api->api_data;
328  if ((node == NULL) && !strcmp(op, CRM_OP_PING)) {
329  sys_to = CRM_SYSTEM_DC;
330  } else {
331  sys_to = CRM_SYSTEM_CRMD;
332  }
333  return create_request(op, msg_data, node, sys_to,
334  (crm_system_name? crm_system_name : "client"),
335  private->client_uuid);
336 }
337 
338 // \return Standard Pacemaker return code
339 static int
340 send_controller_request(pcmk_ipc_api_t *api, const xmlNode *request,
341  bool reply_is_expected)
342 {
343  if (crm_element_value(request, PCMK_XA_REFERENCE) == NULL) {
344  return EINVAL;
345  }
346  if (reply_is_expected) {
347  struct controld_api_private_s *private = api->api_data;
348 
349  private->replies_expected++;
350  }
351  return pcmk__send_ipc_request(api, request);
352 }
353 
354 static xmlNode *
355 create_reprobe_message_data(const char *target_node, const char *router_node)
356 {
357  xmlNode *msg_data;
358 
359  msg_data = pcmk__xe_create(NULL, "data_for_" CRM_OP_REPROBE);
360  crm_xml_add(msg_data, PCMK__META_ON_NODE, target_node);
361  if ((router_node != NULL) && !pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
362  crm_xml_add(msg_data, PCMK__XA_ROUTER_NODE, router_node);
363  }
364  return msg_data;
365 }
366 
377 int
378 pcmk_controld_api_reprobe(pcmk_ipc_api_t *api, const char *target_node,
379  const char *router_node)
380 {
381  xmlNode *request;
382  xmlNode *msg_data;
383  int rc = pcmk_rc_ok;
384 
385  if (api == NULL) {
386  return EINVAL;
387  }
388  if (router_node == NULL) {
389  router_node = target_node;
390  }
391  crm_debug("Sending %s IPC request to reprobe %s via %s",
392  pcmk_ipc_name(api, true), pcmk__s(target_node, "local node"),
393  pcmk__s(router_node, "local node"));
394  msg_data = create_reprobe_message_data(target_node, router_node);
395  request = create_controller_request(api, CRM_OP_REPROBE, router_node,
396  msg_data);
397  rc = send_controller_request(api, request, true);
398  free_xml(msg_data);
399  free_xml(request);
400  return rc;
401 }
402 
412 int
414 {
415  xmlNode *request;
416  int rc = pcmk_rc_ok;
417 
418  request = create_controller_request(api, CRM_OP_NODE_INFO, NULL, NULL);
419  if (request == NULL) {
420  return EINVAL;
421  }
422  if (nodeid > 0) {
423  crm_xml_add_ll(request, PCMK_XA_ID, nodeid);
424  }
425 
426  rc = send_controller_request(api, request, true);
427  free_xml(request);
428  return rc;
429 }
430 
440 int
441 pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
442 {
443  xmlNode *request;
444  int rc = pcmk_rc_ok;
445 
446  request = create_controller_request(api, CRM_OP_PING, node_name, NULL);
447  if (request == NULL) {
448  return EINVAL;
449  }
450  rc = send_controller_request(api, request, true);
451  free_xml(request);
452  return rc;
453 }
454 
463 int
465 {
466  xmlNode *request;
467  int rc = EINVAL;
468 
469  request = create_controller_request(api, PCMK__CONTROLD_CMD_NODES, NULL,
470  NULL);
471  if (request != NULL) {
472  rc = send_controller_request(api, request, true);
473  free_xml(request);
474  }
475  return rc;
476 }
477 
478 // \return Standard Pacemaker return code
479 static int
480 controller_resource_op(pcmk_ipc_api_t *api, const char *op,
481  const char *target_node, const char *router_node,
482  bool cib_only, const char *rsc_id,
483  const char *rsc_long_id, const char *standard,
484  const char *provider, const char *type)
485 {
486  int rc = pcmk_rc_ok;
487  char *key;
488  xmlNode *request, *msg_data, *xml_rsc, *params;
489 
490  if (api == NULL) {
491  return EINVAL;
492  }
493  if (router_node == NULL) {
494  router_node = target_node;
495  }
496 
497  msg_data = pcmk__xe_create(NULL, PCMK__XE_RSC_OP);
498 
499  /* The controller logs the transition key from resource op requests, so we
500  * need to have *something* for it.
501  * @TODO don't use "crm-resource"
502  */
503  key = pcmk__transition_key(0, getpid(), 0,
504  "xxxxxxxx-xrsc-opxx-xcrm-resourcexxxx");
505  crm_xml_add(msg_data, PCMK__XA_TRANSITION_KEY, key);
506  free(key);
507 
508  crm_xml_add(msg_data, PCMK__META_ON_NODE, target_node);
509  if (!pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
510  crm_xml_add(msg_data, PCMK__XA_ROUTER_NODE, router_node);
511  }
512 
513  if (cib_only) {
514  // Indicate that only the CIB needs to be cleaned
516  }
517 
518  xml_rsc = pcmk__xe_create(msg_data, PCMK_XE_PRIMITIVE);
519  crm_xml_add(xml_rsc, PCMK_XA_ID, rsc_id);
520  crm_xml_add(xml_rsc, PCMK__XA_LONG_ID, rsc_long_id);
521  crm_xml_add(xml_rsc, PCMK_XA_CLASS, standard);
522  crm_xml_add(xml_rsc, PCMK_XA_PROVIDER, provider);
523  crm_xml_add(xml_rsc, PCMK_XA_TYPE, type);
524 
525  params = pcmk__xe_create(msg_data, PCMK__XE_ATTRIBUTES);
527 
528  // The controller parses the timeout from the request
530  crm_xml_add(params, key, "60000"); /* 1 minute */ //@TODO pass as arg
531  free(key);
532 
533  request = create_controller_request(api, op, router_node, msg_data);
534  rc = send_controller_request(api, request, true);
535  free_xml(msg_data);
536  free_xml(request);
537  return rc;
538 }
539 
555 int
557  const char *target_node, const char *router_node,
558  const char *rsc_id, const char *rsc_long_id,
559  const char *standard, const char *provider,
560  const char *type)
561 {
562  crm_debug("Sending %s IPC request to fail %s (a.k.a. %s) on %s via %s",
563  pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
564  pcmk__s(rsc_long_id, "no other names"),
565  pcmk__s(target_node, "unspecified node"),
566  pcmk__s(router_node, "unspecified node"));
567  return controller_resource_op(api, CRM_OP_LRM_FAIL, target_node,
568  router_node, false, rsc_id, rsc_long_id,
569  standard, provider, type);
570 }
571 
588 int
589 pcmk_controld_api_refresh(pcmk_ipc_api_t *api, const char *target_node,
590  const char *router_node,
591  const char *rsc_id, const char *rsc_long_id,
592  const char *standard, const char *provider,
593  const char *type, bool cib_only)
594 {
595  crm_debug("Sending %s IPC request to refresh %s (a.k.a. %s) on %s via %s",
596  pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
597  pcmk__s(rsc_long_id, "no other names"),
598  pcmk__s(target_node, "unspecified node"),
599  pcmk__s(router_node, "unspecified node"));
600  return controller_resource_op(api, CRM_OP_LRM_DELETE, target_node,
601  router_node, cib_only, rsc_id, rsc_long_id,
602  standard, provider, type);
603 }
604 
612 unsigned int
614 {
615  struct controld_api_private_s *private = api->api_data;
616 
617  return private->replies_expected;
618 }
619 
625 // \todo make this static to this file when breaking API backward compatibility
626 xmlNode *
627 create_hello_message(const char *uuid, const char *client_name,
628  const char *major_version, const char *minor_version)
629 {
630  xmlNode *hello_node = NULL;
631  xmlNode *hello = NULL;
632 
633  if (pcmk__str_empty(uuid) || pcmk__str_empty(client_name)
634  || pcmk__str_empty(major_version) || pcmk__str_empty(minor_version)) {
635  crm_err("Could not create IPC hello message from %s (UUID %s): "
636  "missing information",
637  client_name? client_name : "unknown client",
638  uuid? uuid : "unknown");
639  return NULL;
640  }
641 
642  hello_node = pcmk__xe_create(NULL, PCMK__XE_OPTIONS);
643  crm_xml_add(hello_node, PCMK__XA_MAJOR_VERSION, major_version);
644  crm_xml_add(hello_node, PCMK__XA_MINOR_VERSION, minor_version);
645  crm_xml_add(hello_node, PCMK__XA_CLIENT_NAME, client_name);
646 
647  // @TODO Nothing uses this. Drop, or keep for debugging?
648  crm_xml_add(hello_node, PCMK__XA_CLIENT_UUID, uuid);
649 
650  hello = create_request(CRM_OP_HELLO, hello_node, NULL, NULL, client_name, uuid);
651  if (hello == NULL) {
652  crm_err("Could not create IPC hello message from %s (UUID %s): "
653  "Request creation failed", client_name, uuid);
654  return NULL;
655  }
656  free_xml(hello_node);
657 
658  crm_trace("Created hello message from %s (UUID %s)", client_name, uuid);
659  return hello;
660 }
A dumping ground.
#define PCMK__VALUE_RESPONSE
union pcmk_controld_api_reply_t::@1 data
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:371
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:378
const char * host_from
Name of node that sent reply.
Definition: ipc_controld.h:61
#define PCMK_XE_PRIMITIVE
Definition: xml_names.h:160
#define CRM_OP_REPROBE
Definition: crm.h:136
#define PCMK__CONTROLD_API_MAJOR
#define CRM_FEATURE_SET
Definition: crm.h:72
#define PCMK_XA_REFERENCE
Definition: xml_names.h:367
#define PCMK_XA_HAVE_QUORUM
Definition: xml_names.h:290
#define PCMK__XA_MODE
#define PCMK__XE_ATTRIBUTES
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:301
#define PCMK_XA_PROVIDER
Definition: xml_names.h:359
char * crm_system_name
Definition: utils.c:50
enum crm_exit_e crm_exit_t
#define PCMK__XA_MAJOR_VERSION
#define PCMK__XA_SUBT
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition: nvpair.c:936
enum crm_ais_msg_types type
Definition: cpg.c:51
#define PCMK__META_ON_NODE
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:501
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: nvpair.c:514
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:482
#define PCMK_XA_TYPE
Definition: xml_names.h:425
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
#define CRM_OP_LRM_FAIL
Definition: crm.h:134
#define CRM_SYSTEM_DC
Definition: crm.h:87
#define PCMK__XA_CRMD_STATE
#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:404
Protocol violated.
Definition: results.h:281
#define crm_debug(fmt, args...)
Definition: logging.h:402
struct pcmk_controld_api_reply_t::@1::@3 resource
#define PCMK_XA_UNAME
Definition: xml_names.h:426
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:446
xmlNode * create_hello_message(const char *uuid, const char *client_name, const char *major_version, const char *minor_version)
Create XML for a controller IPC "hello" message.
Definition: ipc_controld.c:627
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition: xml.c:440
G_GNUC_INTERNAL int pcmk__send_ipc_request(pcmk_ipc_api_t *api, const xmlNode *request)
Definition: ipc_client.c:668
#define crm_trace(fmt, args...)
Definition: logging.h:404
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:292
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:589
#define PCMK__XA_CLIENT_UUID
#define PCMK__XE_RSC_OP
#define PCMK_XA_ID
Definition: xml_names.h:296
Success.
Definition: results.h:255
#define PCMK__XE_OPTIONS
void free_xml(xmlNode *child)
Definition: xml.c:867
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:1050
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:464
#define CRM_SYSTEM_CRMD
Definition: crm.h:90
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: nvpair.c:398
#define PCMK__XA_LONG_ID
#define PCMK_XA_CRM_FEATURE_SET
Definition: xml_names.h:249
#define CRM_XS
Definition: logging.h:56
int(* new_data)(pcmk_ipc_api_t *api)
#define CRM_OP_RM_NODE_CACHE
Definition: crm.h:139
#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:413
#define PCMK__XE_CRM_XML
#define PCMK_XA_CLASS
Definition: xml_names.h:241
#define PCMK_XE_NODE
Definition: xml_names.h:133
bool(* dispatch)(pcmk_ipc_api_t *api, xmlNode *msg)
bool(* reply_expected)(pcmk_ipc_api_t *api, const xmlNode *request)
int pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
Ask the controller for status.
Definition: ipc_controld.c:441
#define CRM_OP_HELLO
Definition: crm.h:124
#define crm_err(fmt, args...)
Definition: logging.h:391
#define PCMK_XA_CRMD
Definition: xml_names.h:251
#define PCMK__XE_ACK
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:613
#define CRM_OP_INVOKE_LRM
Definition: crm.h:131
const char * pcmk__controld_api_reply2str(enum pcmk_controld_api_reply reply)
Definition: ipc_controld.c:41
IPC interface to Pacemaker daemons.
#define CRM_OP_NODE_INFO
Definition: crm.h:120
#define PCMK__CONTROLD_CMD_NODES
Definition: crm_internal.h:85
#define CRM_OP_PING
Definition: crm.h:119
Daemon&#39;s reply to client IPC request.
Definition: ipc.h:96
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
Definition: xml.c:720
#define pcmk__assert_alloc(nmemb, size)
Definition: internal.h:297
#define CRM_OP_LRM_DELETE
Definition: crm.h:133
xmlNode * pcmk__xe_next_same(const xmlNode *node)
Definition: xml.c:2108
#define PCMK_XA_RESULT
Definition: xml_names.h:381
#define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from)
Definition: ipc.h:49
#define PCMK__VALUE_REQUEST
#define crm_info(fmt, args...)
Definition: logging.h:399
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:556
#define PCMK__XA_SRC
#define PCMK__XA_CLIENT_NAME
#define PCMK_XA_VERSION
Definition: xml_names.h:439
pcmk_controld_api_reply
Possible types of controller replies.
Definition: ipc_controld.h:31
char * crm_meta_name(const char *field)
Get the environment variable equivalent of a meta-attribute name.
Definition: nvpair.c:959