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