pacemaker  2.1.6-802a72226b
Scalable High-Availability cluster resource manager
ipc_controld.c
Go to the documentation of this file.
1 /*
2  * Copyright 2020-2022 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 <stdio.h>
13 #include <stdbool.h>
14 #include <errno.h>
15 #include <libxml/tree.h>
16 
17 #include <crm/crm.h>
18 #include <crm/msg_xml.h>
19 #include <crm/common/xml.h>
20 #include <crm/common/ipc.h>
23 #include "crmcommon_private.h"
24 
25 struct controld_api_private_s {
26  char *client_uuid;
27  unsigned int replies_expected;
28 };
29 
38 const char *
40 {
41  switch (reply) {
43  return "reprobe";
45  return "info";
47  return "resource";
49  return "ping";
51  return "nodes";
52  default:
53  return "unknown";
54  }
55 }
56 
57 // \return Standard Pacemaker return code
58 static int
59 new_data(pcmk_ipc_api_t *api)
60 {
61  struct controld_api_private_s *private = NULL;
62 
63  api->api_data = calloc(1, sizeof(struct controld_api_private_s));
64 
65  if (api->api_data == NULL) {
66  return errno;
67  }
68 
69  private = api->api_data;
70 
71  /* This is set to the PID because that's how it was always done, but PIDs
72  * are not unique because clients can be remote. The value appears to be
73  * unused other than as part of F_CRM_SYS_FROM in IPC requests, which is
74  * only compared against the internal system names (CRM_SYSTEM_TENGINE,
75  * etc.), so it shouldn't be a problem.
76  */
77  private->client_uuid = pcmk__getpid_s();
78 
79  /* @TODO Implement a call ID model similar to the CIB, executor, and fencer
80  * IPC APIs, so that requests and replies can be matched, and
81  * duplicate replies can be discarded.
82  */
83  return pcmk_rc_ok;
84 }
85 
86 static void
87 free_data(void *data)
88 {
89  free(((struct controld_api_private_s *) data)->client_uuid);
90  free(data);
91 }
92 
93 // \return Standard Pacemaker return code
94 static int
95 post_connect(pcmk_ipc_api_t *api)
96 {
97  /* The controller currently requires clients to register via a hello
98  * request, but does not reply back.
99  */
100  struct controld_api_private_s *private = api->api_data;
101  const char *client_name = crm_system_name? crm_system_name : "client";
102  xmlNode *hello;
103  int rc;
104 
105  hello = create_hello_message(private->client_uuid, client_name,
108  rc = pcmk__send_ipc_request(api, hello);
109  free_xml(hello);
110  if (rc != pcmk_rc_ok) {
111  crm_info("Could not send IPC hello to %s: %s " CRM_XS " rc=%s",
112  pcmk_ipc_name(api, true), pcmk_rc_str(rc), rc);
113  } else {
114  crm_debug("Sent IPC hello to %s", pcmk_ipc_name(api, true));
115  }
116  return rc;
117 }
118 
119 static void
120 set_node_info_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
121 {
122  data->reply_type = pcmk_controld_reply_info;
123  if (msg_data == NULL) {
124  return;
125  }
126  data->data.node_info.have_quorum = pcmk__xe_attr_is_true(msg_data, XML_ATTR_HAVE_QUORUM);
127  data->data.node_info.is_remote = pcmk__xe_attr_is_true(msg_data, XML_NODE_IS_REMOTE);
128 
129  /* Integer node_info.id is currently valid only for Corosync nodes.
130  *
131  * @TODO: Improve handling after crm_node_t is refactored to handle layer-
132  * specific data better.
133  */
134  crm_element_value_int(msg_data, XML_ATTR_ID, &(data->data.node_info.id));
135 
136  data->data.node_info.uuid = crm_element_value(msg_data, XML_ATTR_ID);
137  data->data.node_info.uname = crm_element_value(msg_data, XML_ATTR_UNAME);
138  data->data.node_info.state = crm_element_value(msg_data, XML_NODE_IS_PEER);
139 }
140 
141 static void
142 set_ping_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
143 {
144  data->reply_type = pcmk_controld_reply_ping;
145  if (msg_data == NULL) {
146  return;
147  }
148  data->data.ping.sys_from = crm_element_value(msg_data,
150  data->data.ping.fsa_state = crm_element_value(msg_data,
152  data->data.ping.result = crm_element_value(msg_data, XML_PING_ATTR_STATUS);
153 }
154 
155 static void
156 set_nodes_data(pcmk_controld_api_reply_t *data, xmlNode *msg_data)
157 {
158  pcmk_controld_api_node_t *node_info;
159 
160  data->reply_type = pcmk_controld_reply_nodes;
161  for (xmlNode *node = first_named_child(msg_data, XML_CIB_TAG_NODE);
162  node != NULL; node = crm_next_same_xml(node)) {
163 
164  long long id_ll = 0;
165 
166  node_info = calloc(1, sizeof(pcmk_controld_api_node_t));
167  crm_element_value_ll(node, XML_ATTR_ID, &id_ll);
168  if (id_ll > 0) {
169  node_info->id = id_ll;
170  }
171  node_info->uname = crm_element_value(node, XML_ATTR_UNAME);
172  node_info->state = crm_element_value(node, XML_NODE_IN_CLUSTER);
173  data->data.nodes = g_list_prepend(data->data.nodes, node_info);
174  }
175 }
176 
177 static bool
178 reply_expected(pcmk_ipc_api_t *api, xmlNode *request)
179 {
180  const char *command = crm_element_value(request, F_CRM_TASK);
181 
182  if (command == NULL) {
183  return false;
184  }
185 
186  // We only need to handle commands that functions in this file can send
187  return !strcmp(command, CRM_OP_REPROBE)
188  || !strcmp(command, CRM_OP_NODE_INFO)
189  || !strcmp(command, CRM_OP_PING)
190  || !strcmp(command, CRM_OP_LRM_FAIL)
191  || !strcmp(command, CRM_OP_LRM_DELETE);
192 }
193 
194 static bool
195 dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
196 {
197  struct controld_api_private_s *private = api->api_data;
198  crm_exit_t status = CRM_EX_OK;
199  xmlNode *msg_data = NULL;
200  const char *value = NULL;
201  pcmk_controld_api_reply_t reply_data = {
202  pcmk_controld_reply_unknown, NULL, NULL,
203  };
204 
205  /* If we got an ACK, return true so the caller knows to expect more responses
206  * from the IPC server. We do this before decrementing replies_expected because
207  * ACKs are not going to be included in that value.
208  *
209  * Note that we cannot do the same kind of status checking here that we do in
210  * ipc_pacemakerd.c. The ACK message we receive does not necessarily contain
211  * a status attribute. That is, we may receive this:
212  *
213  * <ack function="crmd_remote_proxy_cb" line="556"/>
214  *
215  * Instead of this:
216  *
217  * <ack function="dispatch_controller_ipc" line="391" status="112"/>
218  */
219  if (pcmk__str_eq(crm_element_name(reply), "ack", pcmk__str_none)) {
220  return true; // More replies needed
221  }
222 
223  if (private->replies_expected > 0) {
224  private->replies_expected--;
225  }
226 
227  // Do some basic validation of the reply
228 
229  /* @TODO We should be able to verify that value is always a response, but
230  * currently the controller doesn't always properly set the type. Even
231  * if we fix the controller, we'll still need to handle replies from
232  * old versions (feature set could be used to differentiate).
233  */
234  value = crm_element_value(reply, F_CRM_MSG_TYPE);
235  if (pcmk__str_empty(value)
237  crm_info("Unrecognizable message from controller: "
238  "invalid message type '%s'", pcmk__s(value, ""));
239  status = CRM_EX_PROTOCOL;
240  goto done;
241  }
242 
243  if (pcmk__str_empty(crm_element_value(reply, XML_ATTR_REFERENCE))) {
244  crm_info("Unrecognizable message from controller: no reference");
245  status = CRM_EX_PROTOCOL;
246  goto done;
247  }
248 
249  value = crm_element_value(reply, F_CRM_TASK);
250  if (pcmk__str_empty(value)) {
251  crm_info("Unrecognizable message from controller: no command name");
252  status = CRM_EX_PROTOCOL;
253  goto done;
254  }
255 
256  // Parse useful info from reply
257 
258  reply_data.feature_set = crm_element_value(reply, XML_ATTR_VERSION);
259  reply_data.host_from = crm_element_value(reply, F_CRM_HOST_FROM);
260  msg_data = get_message_xml(reply, F_CRM_DATA);
261 
262  if (!strcmp(value, CRM_OP_REPROBE)) {
264 
265  } else if (!strcmp(value, CRM_OP_NODE_INFO)) {
266  set_node_info_data(&reply_data, msg_data);
267 
268  } else if (!strcmp(value, CRM_OP_INVOKE_LRM)) {
270  reply_data.data.resource.node_state = msg_data;
271 
272  } else if (!strcmp(value, CRM_OP_PING)) {
273  set_ping_data(&reply_data, msg_data);
274 
275  } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
276  set_nodes_data(&reply_data, msg_data);
277 
278  } else {
279  crm_info("Unrecognizable message from controller: unknown command '%s'",
280  value);
281  status = CRM_EX_PROTOCOL;
282  }
283 
284 done:
285  pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
286 
287  // Free any reply data that was allocated
288  if (pcmk__str_eq(value, PCMK__CONTROLD_CMD_NODES, pcmk__str_casei)) {
289  g_list_free_full(reply_data.data.nodes, free);
290  }
291 
292  return false; // No further replies needed
293 }
294 
297 {
298  pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
299 
300  if (cmds != NULL) {
301  cmds->new_data = new_data;
302  cmds->free_data = free_data;
303  cmds->post_connect = post_connect;
304  cmds->reply_expected = reply_expected;
305  cmds->dispatch = dispatch;
306  }
307  return cmds;
308 }
309 
321 static xmlNode *
322 create_controller_request(const pcmk_ipc_api_t *api, const char *op,
323  const char *node, xmlNode *msg_data)
324 {
325  struct controld_api_private_s *private = NULL;
326  const char *sys_to = NULL;
327 
328  if (api == NULL) {
329  return NULL;
330  }
331  private = api->api_data;
332  if ((node == NULL) && !strcmp(op, CRM_OP_PING)) {
333  sys_to = CRM_SYSTEM_DC;
334  } else {
335  sys_to = CRM_SYSTEM_CRMD;
336  }
337  return create_request(op, msg_data, node, sys_to,
338  (crm_system_name? crm_system_name : "client"),
339  private->client_uuid);
340 }
341 
342 // \return Standard Pacemaker return code
343 static int
344 send_controller_request(pcmk_ipc_api_t *api, xmlNode *request,
345  bool reply_is_expected)
346 {
347  int rc;
348 
349  if (crm_element_value(request, XML_ATTR_REFERENCE) == NULL) {
350  return EINVAL;
351  }
352  rc = pcmk__send_ipc_request(api, request);
353  if ((rc == pcmk_rc_ok) && reply_is_expected) {
354  struct controld_api_private_s *private = api->api_data;
355 
356  private->replies_expected++;
357  }
358  return rc;
359 }
360 
361 static xmlNode *
362 create_reprobe_message_data(const char *target_node, const char *router_node)
363 {
364  xmlNode *msg_data;
365 
366  msg_data = create_xml_node(NULL, "data_for_" CRM_OP_REPROBE);
367  crm_xml_add(msg_data, XML_LRM_ATTR_TARGET, target_node);
368  if ((router_node != NULL) && !pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
369  crm_xml_add(msg_data, XML_LRM_ATTR_ROUTER_NODE, router_node);
370  }
371  return msg_data;
372 }
373 
384 int
385 pcmk_controld_api_reprobe(pcmk_ipc_api_t *api, const char *target_node,
386  const char *router_node)
387 {
388  xmlNode *request;
389  xmlNode *msg_data;
390  int rc = pcmk_rc_ok;
391 
392  if (api == NULL) {
393  return EINVAL;
394  }
395  if (router_node == NULL) {
396  router_node = target_node;
397  }
398  crm_debug("Sending %s IPC request to reprobe %s via %s",
399  pcmk_ipc_name(api, true), pcmk__s(target_node, "local node"),
400  pcmk__s(router_node, "local node"));
401  msg_data = create_reprobe_message_data(target_node, router_node);
402  request = create_controller_request(api, CRM_OP_REPROBE, router_node,
403  msg_data);
404  rc = send_controller_request(api, request, true);
405  free_xml(msg_data);
406  free_xml(request);
407  return rc;
408 }
409 
419 int
421 {
422  xmlNode *request;
423  int rc = pcmk_rc_ok;
424 
425  request = create_controller_request(api, CRM_OP_NODE_INFO, NULL, NULL);
426  if (request == NULL) {
427  return EINVAL;
428  }
429  if (nodeid > 0) {
430  crm_xml_set_id(request, "%lu", (unsigned long) nodeid);
431  }
432 
433  rc = send_controller_request(api, request, true);
434  free_xml(request);
435  return rc;
436 }
437 
447 int
448 pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
449 {
450  xmlNode *request;
451  int rc = pcmk_rc_ok;
452 
453  request = create_controller_request(api, CRM_OP_PING, node_name, NULL);
454  if (request == NULL) {
455  return EINVAL;
456  }
457  rc = send_controller_request(api, request, true);
458  free_xml(request);
459  return rc;
460 }
461 
470 int
472 {
473  xmlNode *request;
474  int rc = EINVAL;
475 
476  request = create_controller_request(api, PCMK__CONTROLD_CMD_NODES, NULL,
477  NULL);
478  if (request != NULL) {
479  rc = send_controller_request(api, request, true);
480  free_xml(request);
481  }
482  return rc;
483 }
484 
485 // \return Standard Pacemaker return code
486 static int
487 controller_resource_op(pcmk_ipc_api_t *api, const char *op,
488  const char *target_node, const char *router_node,
489  bool cib_only, const char *rsc_id,
490  const char *rsc_long_id, const char *standard,
491  const char *provider, const char *type)
492 {
493  int rc = pcmk_rc_ok;
494  char *key;
495  xmlNode *request, *msg_data, *xml_rsc, *params;
496 
497  if (api == NULL) {
498  return EINVAL;
499  }
500  if (router_node == NULL) {
501  router_node = target_node;
502  }
503 
504  msg_data = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
505 
506  /* The controller logs the transition key from resource op requests, so we
507  * need to have *something* for it.
508  * @TODO don't use "crm-resource"
509  */
510  key = pcmk__transition_key(0, getpid(), 0,
511  "xxxxxxxx-xrsc-opxx-xcrm-resourcexxxx");
512  crm_xml_add(msg_data, XML_ATTR_TRANSITION_KEY, key);
513  free(key);
514 
515  crm_xml_add(msg_data, XML_LRM_ATTR_TARGET, target_node);
516  if (!pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
517  crm_xml_add(msg_data, XML_LRM_ATTR_ROUTER_NODE, router_node);
518  }
519 
520  if (cib_only) {
521  // Indicate that only the CIB needs to be cleaned
523  }
524 
525  xml_rsc = create_xml_node(msg_data, XML_CIB_TAG_RESOURCE);
526  crm_xml_add(xml_rsc, XML_ATTR_ID, rsc_id);
527  crm_xml_add(xml_rsc, XML_ATTR_ID_LONG, rsc_long_id);
528  crm_xml_add(xml_rsc, XML_AGENT_ATTR_CLASS, standard);
529  crm_xml_add(xml_rsc, XML_AGENT_ATTR_PROVIDER, provider);
530  crm_xml_add(xml_rsc, XML_ATTR_TYPE, type);
531 
532  params = create_xml_node(msg_data, XML_TAG_ATTRS);
534 
535  // The controller parses the timeout from the request
537  crm_xml_add(params, key, "60000"); /* 1 minute */ //@TODO pass as arg
538  free(key);
539 
540  request = create_controller_request(api, op, router_node, msg_data);
541  rc = send_controller_request(api, request, true);
542  free_xml(msg_data);
543  free_xml(request);
544  return rc;
545 }
546 
562 int
564  const char *target_node, const char *router_node,
565  const char *rsc_id, const char *rsc_long_id,
566  const char *standard, const char *provider,
567  const char *type)
568 {
569  crm_debug("Sending %s IPC request to fail %s (a.k.a. %s) on %s via %s",
570  pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
571  pcmk__s(rsc_long_id, "no other names"),
572  pcmk__s(target_node, "unspecified node"),
573  pcmk__s(router_node, "unspecified node"));
574  return controller_resource_op(api, CRM_OP_LRM_FAIL, target_node,
575  router_node, false, rsc_id, rsc_long_id,
576  standard, provider, type);
577 }
578 
595 int
596 pcmk_controld_api_refresh(pcmk_ipc_api_t *api, const char *target_node,
597  const char *router_node,
598  const char *rsc_id, const char *rsc_long_id,
599  const char *standard, const char *provider,
600  const char *type, bool cib_only)
601 {
602  crm_debug("Sending %s IPC request to refresh %s (a.k.a. %s) on %s via %s",
603  pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
604  pcmk__s(rsc_long_id, "no other names"),
605  pcmk__s(target_node, "unspecified node"),
606  pcmk__s(router_node, "unspecified node"));
607  return controller_resource_op(api, CRM_OP_LRM_DELETE, target_node,
608  router_node, cib_only, rsc_id, rsc_long_id,
609  standard, provider, type);
610 }
611 
619 unsigned int
621 {
622  struct controld_api_private_s *private = api->api_data;
623 
624  return private->replies_expected;
625 }
626 
632 // \todo make this static to this file when breaking API backward compatibility
633 xmlNode *
634 create_hello_message(const char *uuid, const char *client_name,
635  const char *major_version, const char *minor_version)
636 {
637  xmlNode *hello_node = NULL;
638  xmlNode *hello = NULL;
639 
640  if (pcmk__str_empty(uuid) || pcmk__str_empty(client_name)
641  || pcmk__str_empty(major_version) || pcmk__str_empty(minor_version)) {
642  crm_err("Could not create IPC hello message from %s (UUID %s): "
643  "missing information",
644  client_name? client_name : "unknown client",
645  uuid? uuid : "unknown");
646  return NULL;
647  }
648 
649  hello_node = create_xml_node(NULL, XML_TAG_OPTIONS);
650  if (hello_node == NULL) {
651  crm_err("Could not create IPC hello message from %s (UUID %s): "
652  "Message data creation failed", client_name, uuid);
653  return NULL;
654  }
655 
656  crm_xml_add(hello_node, "major_version", major_version);
657  crm_xml_add(hello_node, "minor_version", minor_version);
658  crm_xml_add(hello_node, "client_name", client_name);
659  crm_xml_add(hello_node, "client_uuid", uuid);
660 
661  hello = create_request(CRM_OP_HELLO, hello_node, NULL, NULL, client_name, uuid);
662  if (hello == NULL) {
663  crm_err("Could not create IPC hello message from %s (UUID %s): "
664  "Request creation failed", client_name, uuid);
665  return NULL;
666  }
667  free_xml(hello_node);
668 
669  crm_trace("Created hello message from %s (UUID %s)", client_name, uuid);
670  return hello;
671 }
#define XML_ATTR_ID_LONG
Definition: msg_xml.h:150
#define F_CRM_TASK
Definition: msg_xml.h:104
A dumping ground.
union pcmk_controld_api_reply_t::@1 data
char data[0]
Definition: cpg.c:55
enum pcmk_controld_api_reply reply_type
Definition: ipc_controld.h:59
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:385
#define XML_TAG_OPTIONS
Definition: msg_xml.h:164
#define XML_ATTR_VERSION
Definition: msg_xml.h:145
const char * host_from
Name of node that sent reply.
Definition: ipc_controld.h:61
#define XML_ATTR_TYPE
Definition: msg_xml.h:151
#define CRM_OP_REPROBE
Definition: crm.h:152
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2521
#define PCMK__CONTROLD_API_MAJOR
#define F_CRM_MSG_TYPE
Definition: msg_xml.h:106
#define CRM_FEATURE_SET
Definition: crm.h:69
#define F_CRM_HOST_FROM
Definition: msg_xml.h:109
#define XML_TAG_ATTRS
Definition: msg_xml.h:224
#define XML_PING_ATTR_CRMDSTATE
Definition: msg_xml.h:176
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:302
#define XML_ATTR_TIMEOUT
Definition: msg_xml.h:141
#define XML_GRAPH_TAG_RSC_OP
Definition: msg_xml.h:344
char * crm_system_name
Definition: utils.c:51
enum crm_exit_e crm_exit_t
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition: nvpair.c:954
enum crm_ais_msg_types type
Definition: cpg.c:48
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: results.c:488
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:564
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:532
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:146
char * crm_meta_name(const char *field)
Definition: utils.c:468
#define CRM_OP_LRM_FAIL
Definition: crm.h:150
#define CRM_SYSTEM_DC
Definition: crm.h:102
#define XML_ATTR_REQUEST
Definition: msg_xml.h:167
#define PCMK__CONTROLD_API_MINOR
Protocol violated.
Definition: results.h:263
#define crm_debug(fmt, args...)
Definition: logging.h:382
struct pcmk_controld_api_reply_t::@1::@3 resource
#define XML_ATTR_ID
Definition: msg_xml.h:147
#define XML_PING_ATTR_STATUS
Definition: msg_xml.h:174
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:496
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:230
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:634
#define XML_NODE_IS_PEER
Definition: msg_xml.h:296
#define crm_trace(fmt, args...)
Definition: logging.h:383
const char * feature_set
CRM feature set advertised by controller.
Definition: ipc_controld.h:60
void crm_xml_set_id(xmlNode *xml, const char *format,...) G_GNUC_PRINTF(2
pcmk__ipc_methods_t * pcmk__controld_api_methods(void)
Definition: ipc_controld.c:296
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:283
#define XML_ATTR_HAVE_QUORUM
Definition: msg_xml.h:136
Wrappers for and extensions to libxml2.
#define XML_ATTR_UNAME
Definition: msg_xml.h:170
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:596
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:677
G_GNUC_INTERNAL int pcmk__send_ipc_request(pcmk_ipc_api_t *api, xmlNode *request)
Definition: ipc_client.c:639
Success.
Definition: results.h:237
#define XML_NODE_IS_REMOTE
Definition: msg_xml.h:297
#define XML_LRM_ATTR_ROUTER_NODE
Definition: msg_xml.h:323
void free_xml(xmlNode *child)
Definition: xml.c:813
int(* post_connect)(pcmk_ipc_api_t *api)
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition: strings.c:957
xmlNode * get_message_xml(const xmlNode *msg, const char *field)
Definition: messages.c:154
#define XML_CIB_TAG_NODE
Definition: msg_xml.h:218
IPC commands for Pacemaker controller.
int pcmk_controld_api_list_nodes(pcmk_ipc_api_t *api)
Ask the controller for cluster information.
Definition: ipc_controld.c:471
#define CRM_SYSTEM_CRMD
Definition: crm.h:105
#define XML_PING_ATTR_SYSFROM
Definition: msg_xml.h:175
#define F_CRM_DATA
Definition: msg_xml.h:103
#define XML_ATTR_TRANSITION_KEY
Definition: msg_xml.h:425
#define CRM_XS
Definition: logging.h:55
#define XML_TAG_CIB
Definition: msg_xml.h:128
int(* new_data)(pcmk_ipc_api_t *api)
int pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
Send a "node info" controller operation.
Definition: ipc_controld.c:420
bool(* dispatch)(pcmk_ipc_api_t *api, xmlNode *msg)
int pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
Ask the controller for status.
Definition: ipc_controld.c:448
#define CRM_OP_HELLO
Definition: crm.h:138
#define crm_err(fmt, args...)
Definition: logging.h:377
#define XML_ATTR_REFERENCE
Definition: msg_xml.h:171
#define PCMK__XA_MODE
Definition: crm_internal.h:86
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:243
#define XML_ATTR_RESPONSE
Definition: msg_xml.h:168
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:620
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:131
char * pcmk__transition_key(int transition_id, int action_id, int target_rc, const char *node)
Definition: operations.c:250
bool(* reply_expected)(pcmk_ipc_api_t *api, xmlNode *request)
#define CRM_OP_INVOKE_LRM
Definition: crm.h:147
const char * pcmk__controld_api_reply2str(enum pcmk_controld_api_reply reply)
Definition: ipc_controld.c:39
IPC interface to Pacemaker daemons.
#define CRM_OP_NODE_INFO
Definition: crm.h:134
#define XML_NODE_IN_CLUSTER
Definition: msg_xml.h:295
#define PCMK__CONTROLD_CMD_NODES
Definition: crm_internal.h:116
#define CRM_OP_PING
Definition: crm.h:133
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:317
Daemon&#39;s reply to client IPC request.
Definition: ipc.h:83
#define CRM_OP_LRM_DELETE
Definition: crm.h:149
#define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from)
Definition: ipc.h:43
#define crm_info(fmt, args...)
Definition: logging.h:380
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:563
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:282
pcmk_controld_api_reply
Possible types of controller replies.
Definition: ipc_controld.h:31
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition: xml.c:2547