pacemaker  2.1.7-0f7f88312f
Scalable High-Availability cluster resource manager
ipc_controld.c
Go to the documentation of this file.
1 /*
2  * Copyright 2020-2023 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, PCMK__XA_CRMD);
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, PCMK__XA_IN_CCM);
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, const xmlNode *request)
179 {
180  // We only need to handle commands that API functions can send
186  CRM_OP_PING,
189  NULL);
190 }
191 
192 static bool
193 dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
194 {
195  struct controld_api_private_s *private = api->api_data;
196  crm_exit_t status = CRM_EX_OK;
197  xmlNode *msg_data = NULL;
198  const char *value = NULL;
199  pcmk_controld_api_reply_t reply_data = {
200  pcmk_controld_reply_unknown, NULL, NULL,
201  };
202 
203  if (pcmk__xe_is(reply, "ack")) {
204  /* ACKs are trivial responses that do not count toward expected replies,
205  * and do not have all the fields that validation requires, so skip that
206  * processing.
207  */
208  return private->replies_expected > 0;
209  }
210 
211  if (private->replies_expected > 0) {
212  private->replies_expected--;
213  }
214 
215  // Do some basic validation of the reply
216 
217  /* @TODO We should be able to verify that value is always a response, but
218  * currently the controller doesn't always properly set the type. Even
219  * if we fix the controller, we'll still need to handle replies from
220  * old versions (feature set could be used to differentiate).
221  */
222  value = crm_element_value(reply, F_CRM_MSG_TYPE);
223  if (pcmk__str_empty(value)
225  crm_info("Unrecognizable message from controller: "
226  "invalid message type '%s'", pcmk__s(value, ""));
227  status = CRM_EX_PROTOCOL;
228  goto done;
229  }
230 
231  if (pcmk__str_empty(crm_element_value(reply, XML_ATTR_REFERENCE))) {
232  crm_info("Unrecognizable message from controller: no reference");
233  status = CRM_EX_PROTOCOL;
234  goto done;
235  }
236 
237  value = crm_element_value(reply, F_CRM_TASK);
238  if (pcmk__str_empty(value)) {
239  crm_info("Unrecognizable message from controller: no command name");
240  status = CRM_EX_PROTOCOL;
241  goto done;
242  }
243 
244  // Parse useful info from reply
245 
246  reply_data.feature_set = crm_element_value(reply, XML_ATTR_VERSION);
247  reply_data.host_from = crm_element_value(reply, F_CRM_HOST_FROM);
248  msg_data = get_message_xml(reply, F_CRM_DATA);
249 
250  if (!strcmp(value, CRM_OP_REPROBE)) {
252 
253  } else if (!strcmp(value, CRM_OP_NODE_INFO)) {
254  set_node_info_data(&reply_data, msg_data);
255 
256  } else if (!strcmp(value, CRM_OP_INVOKE_LRM)) {
258  reply_data.data.resource.node_state = msg_data;
259 
260  } else if (!strcmp(value, CRM_OP_PING)) {
261  set_ping_data(&reply_data, msg_data);
262 
263  } else if (!strcmp(value, PCMK__CONTROLD_CMD_NODES)) {
264  set_nodes_data(&reply_data, msg_data);
265 
266  } else {
267  crm_info("Unrecognizable message from controller: unknown command '%s'",
268  value);
269  status = CRM_EX_PROTOCOL;
270  }
271 
272 done:
273  pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
274 
275  // Free any reply data that was allocated
276  if (pcmk__str_eq(value, PCMK__CONTROLD_CMD_NODES, pcmk__str_casei)) {
277  g_list_free_full(reply_data.data.nodes, free);
278  }
279 
280  return false; // No further replies needed
281 }
282 
285 {
286  pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
287 
288  if (cmds != NULL) {
289  cmds->new_data = new_data;
290  cmds->free_data = free_data;
291  cmds->post_connect = post_connect;
292  cmds->reply_expected = reply_expected;
293  cmds->dispatch = dispatch;
294  }
295  return cmds;
296 }
297 
309 static xmlNode *
310 create_controller_request(const pcmk_ipc_api_t *api, const char *op,
311  const char *node, xmlNode *msg_data)
312 {
313  struct controld_api_private_s *private = NULL;
314  const char *sys_to = NULL;
315 
316  if (api == NULL) {
317  return NULL;
318  }
319  private = api->api_data;
320  if ((node == NULL) && !strcmp(op, CRM_OP_PING)) {
321  sys_to = CRM_SYSTEM_DC;
322  } else {
323  sys_to = CRM_SYSTEM_CRMD;
324  }
325  return create_request(op, msg_data, node, sys_to,
326  (crm_system_name? crm_system_name : "client"),
327  private->client_uuid);
328 }
329 
330 // \return Standard Pacemaker return code
331 static int
332 send_controller_request(pcmk_ipc_api_t *api, const xmlNode *request,
333  bool reply_is_expected)
334 {
335  if (crm_element_value(request, XML_ATTR_REFERENCE) == NULL) {
336  return EINVAL;
337  }
338  if (reply_is_expected) {
339  struct controld_api_private_s *private = api->api_data;
340 
341  private->replies_expected++;
342  }
343  return pcmk__send_ipc_request(api, request);
344 }
345 
346 static xmlNode *
347 create_reprobe_message_data(const char *target_node, const char *router_node)
348 {
349  xmlNode *msg_data;
350 
351  msg_data = create_xml_node(NULL, "data_for_" CRM_OP_REPROBE);
352  crm_xml_add(msg_data, XML_LRM_ATTR_TARGET, target_node);
353  if ((router_node != NULL) && !pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
354  crm_xml_add(msg_data, XML_LRM_ATTR_ROUTER_NODE, router_node);
355  }
356  return msg_data;
357 }
358 
369 int
370 pcmk_controld_api_reprobe(pcmk_ipc_api_t *api, const char *target_node,
371  const char *router_node)
372 {
373  xmlNode *request;
374  xmlNode *msg_data;
375  int rc = pcmk_rc_ok;
376 
377  if (api == NULL) {
378  return EINVAL;
379  }
380  if (router_node == NULL) {
381  router_node = target_node;
382  }
383  crm_debug("Sending %s IPC request to reprobe %s via %s",
384  pcmk_ipc_name(api, true), pcmk__s(target_node, "local node"),
385  pcmk__s(router_node, "local node"));
386  msg_data = create_reprobe_message_data(target_node, router_node);
387  request = create_controller_request(api, CRM_OP_REPROBE, router_node,
388  msg_data);
389  rc = send_controller_request(api, request, true);
390  free_xml(msg_data);
391  free_xml(request);
392  return rc;
393 }
394 
404 int
406 {
407  xmlNode *request;
408  int rc = pcmk_rc_ok;
409 
410  request = create_controller_request(api, CRM_OP_NODE_INFO, NULL, NULL);
411  if (request == NULL) {
412  return EINVAL;
413  }
414  if (nodeid > 0) {
415  crm_xml_set_id(request, "%lu", (unsigned long) nodeid);
416  }
417 
418  rc = send_controller_request(api, request, true);
419  free_xml(request);
420  return rc;
421 }
422 
432 int
433 pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
434 {
435  xmlNode *request;
436  int rc = pcmk_rc_ok;
437 
438  request = create_controller_request(api, CRM_OP_PING, node_name, NULL);
439  if (request == NULL) {
440  return EINVAL;
441  }
442  rc = send_controller_request(api, request, true);
443  free_xml(request);
444  return rc;
445 }
446 
455 int
457 {
458  xmlNode *request;
459  int rc = EINVAL;
460 
461  request = create_controller_request(api, PCMK__CONTROLD_CMD_NODES, NULL,
462  NULL);
463  if (request != NULL) {
464  rc = send_controller_request(api, request, true);
465  free_xml(request);
466  }
467  return rc;
468 }
469 
470 // \return Standard Pacemaker return code
471 static int
472 controller_resource_op(pcmk_ipc_api_t *api, const char *op,
473  const char *target_node, const char *router_node,
474  bool cib_only, const char *rsc_id,
475  const char *rsc_long_id, const char *standard,
476  const char *provider, const char *type)
477 {
478  int rc = pcmk_rc_ok;
479  char *key;
480  xmlNode *request, *msg_data, *xml_rsc, *params;
481 
482  if (api == NULL) {
483  return EINVAL;
484  }
485  if (router_node == NULL) {
486  router_node = target_node;
487  }
488 
489  msg_data = create_xml_node(NULL, XML_GRAPH_TAG_RSC_OP);
490 
491  /* The controller logs the transition key from resource op requests, so we
492  * need to have *something* for it.
493  * @TODO don't use "crm-resource"
494  */
495  key = pcmk__transition_key(0, getpid(), 0,
496  "xxxxxxxx-xrsc-opxx-xcrm-resourcexxxx");
497  crm_xml_add(msg_data, XML_ATTR_TRANSITION_KEY, key);
498  free(key);
499 
500  crm_xml_add(msg_data, XML_LRM_ATTR_TARGET, target_node);
501  if (!pcmk__str_eq(router_node, target_node, pcmk__str_casei)) {
502  crm_xml_add(msg_data, XML_LRM_ATTR_ROUTER_NODE, router_node);
503  }
504 
505  if (cib_only) {
506  // Indicate that only the CIB needs to be cleaned
508  }
509 
510  xml_rsc = create_xml_node(msg_data, XML_CIB_TAG_RESOURCE);
511  crm_xml_add(xml_rsc, XML_ATTR_ID, rsc_id);
512  crm_xml_add(xml_rsc, XML_ATTR_ID_LONG, rsc_long_id);
513  crm_xml_add(xml_rsc, XML_AGENT_ATTR_CLASS, standard);
514  crm_xml_add(xml_rsc, XML_AGENT_ATTR_PROVIDER, provider);
515  crm_xml_add(xml_rsc, XML_ATTR_TYPE, type);
516 
517  params = create_xml_node(msg_data, XML_TAG_ATTRS);
519 
520  // The controller parses the timeout from the request
522  crm_xml_add(params, key, "60000"); /* 1 minute */ //@TODO pass as arg
523  free(key);
524 
525  request = create_controller_request(api, op, router_node, msg_data);
526  rc = send_controller_request(api, request, true);
527  free_xml(msg_data);
528  free_xml(request);
529  return rc;
530 }
531 
547 int
549  const char *target_node, const char *router_node,
550  const char *rsc_id, const char *rsc_long_id,
551  const char *standard, const char *provider,
552  const char *type)
553 {
554  crm_debug("Sending %s IPC request to fail %s (a.k.a. %s) on %s via %s",
555  pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
556  pcmk__s(rsc_long_id, "no other names"),
557  pcmk__s(target_node, "unspecified node"),
558  pcmk__s(router_node, "unspecified node"));
559  return controller_resource_op(api, CRM_OP_LRM_FAIL, target_node,
560  router_node, false, rsc_id, rsc_long_id,
561  standard, provider, type);
562 }
563 
580 int
581 pcmk_controld_api_refresh(pcmk_ipc_api_t *api, const char *target_node,
582  const char *router_node,
583  const char *rsc_id, const char *rsc_long_id,
584  const char *standard, const char *provider,
585  const char *type, bool cib_only)
586 {
587  crm_debug("Sending %s IPC request to refresh %s (a.k.a. %s) on %s via %s",
588  pcmk_ipc_name(api, true), pcmk__s(rsc_id, "unknown resource"),
589  pcmk__s(rsc_long_id, "no other names"),
590  pcmk__s(target_node, "unspecified node"),
591  pcmk__s(router_node, "unspecified node"));
592  return controller_resource_op(api, CRM_OP_LRM_DELETE, target_node,
593  router_node, cib_only, rsc_id, rsc_long_id,
594  standard, provider, type);
595 }
596 
604 unsigned int
606 {
607  struct controld_api_private_s *private = api->api_data;
608 
609  return private->replies_expected;
610 }
611 
617 // \todo make this static to this file when breaking API backward compatibility
618 xmlNode *
619 create_hello_message(const char *uuid, const char *client_name,
620  const char *major_version, const char *minor_version)
621 {
622  xmlNode *hello_node = NULL;
623  xmlNode *hello = NULL;
624 
625  if (pcmk__str_empty(uuid) || pcmk__str_empty(client_name)
626  || pcmk__str_empty(major_version) || pcmk__str_empty(minor_version)) {
627  crm_err("Could not create IPC hello message from %s (UUID %s): "
628  "missing information",
629  client_name? client_name : "unknown client",
630  uuid? uuid : "unknown");
631  return NULL;
632  }
633 
634  hello_node = create_xml_node(NULL, XML_TAG_OPTIONS);
635  if (hello_node == NULL) {
636  crm_err("Could not create IPC hello message from %s (UUID %s): "
637  "Message data creation failed", client_name, uuid);
638  return NULL;
639  }
640 
641  crm_xml_add(hello_node, "major_version", major_version);
642  crm_xml_add(hello_node, "minor_version", minor_version);
643  crm_xml_add(hello_node, "client_name", client_name);
644  crm_xml_add(hello_node, "client_uuid", uuid);
645 
646  hello = create_request(CRM_OP_HELLO, hello_node, NULL, NULL, client_name, uuid);
647  if (hello == NULL) {
648  crm_err("Could not create IPC hello message from %s (UUID %s): "
649  "Request creation failed", client_name, uuid);
650  return NULL;
651  }
652  free_xml(hello_node);
653 
654  crm_trace("Created hello message from %s (UUID %s)", client_name, uuid);
655  return hello;
656 }
#define XML_ATTR_ID_LONG
Definition: msg_xml.h:159
#define F_CRM_TASK
Definition: msg_xml.h:113
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:370
#define XML_TAG_OPTIONS
Definition: msg_xml.h:172
#define XML_ATTR_VERSION
Definition: msg_xml.h:154
const char * host_from
Name of node that sent reply.
Definition: ipc_controld.h:61
#define XML_ATTR_TYPE
Definition: msg_xml.h:160
#define CRM_OP_REPROBE
Definition: crm.h:151
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition: xml.c:2484
#define PCMK__CONTROLD_API_MAJOR
#define F_CRM_MSG_TYPE
Definition: msg_xml.h:115
#define CRM_FEATURE_SET
Definition: crm.h:70
#define F_CRM_HOST_FROM
Definition: msg_xml.h:118
#define XML_TAG_ATTRS
Definition: msg_xml.h:229
#define XML_PING_ATTR_CRMDSTATE
Definition: msg_xml.h:184
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:150
#define XML_GRAPH_TAG_RSC_OP
Definition: msg_xml.h:334
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:905
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: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:515
int crm_element_value_int(const xmlNode *data, const char *name, int *dest)
Retrieve the integer value of an XML attribute.
Definition: nvpair.c:483
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
char * crm_meta_name(const char *field)
Definition: utils.c:468
#define CRM_OP_LRM_FAIL
Definition: crm.h:149
#define CRM_SYSTEM_DC
Definition: crm.h:101
#define PCMK__XA_CRMD
Definition: crm_internal.h:84
#define XML_ATTR_REQUEST
Definition: msg_xml.h:175
#define PCMK__CONTROLD_API_MINOR
char * pcmk__transition_key(int transition_id, int action_id, int target_rc, const char *node)
Definition: actions.c:250
Protocol violated.
Definition: results.h:266
#define crm_debug(fmt, args...)
Definition: logging.h:386
struct pcmk_controld_api_reply_t::@1::@3 resource
#define XML_ATTR_ID
Definition: msg_xml.h:156
#define XML_PING_ATTR_STATUS
Definition: msg_xml.h:182
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:447
#define XML_CIB_TAG_RESOURCE
Definition: msg_xml.h:235
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:619
#define PCMK__XA_IN_CCM
Definition: crm_internal.h:88
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:387
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:284
#define XML_AGENT_ATTR_PROVIDER
Definition: msg_xml.h:281
#define XML_ATTR_HAVE_QUORUM
Definition: msg_xml.h:145
Wrappers for and extensions to libxml2.
#define XML_ATTR_UNAME
Definition: msg_xml.h:178
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:581
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:638
Success.
Definition: results.h:240
#define XML_NODE_IS_REMOTE
Definition: msg_xml.h:288
#define XML_LRM_ATTR_ROUTER_NODE
Definition: msg_xml.h:314
void free_xml(xmlNode *child)
Definition: xml.c:783
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:223
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:456
#define CRM_SYSTEM_CRMD
Definition: crm.h:104
#define XML_PING_ATTR_SYSFROM
Definition: msg_xml.h:183
#define F_CRM_DATA
Definition: msg_xml.h:112
#define XML_ATTR_TRANSITION_KEY
Definition: msg_xml.h:416
#define CRM_XS
Definition: logging.h:56
#define XML_TAG_CIB
Definition: msg_xml.h:137
int(* new_data)(pcmk_ipc_api_t *api)
#define CRM_OP_RM_NODE_CACHE
Definition: crm.h:154
int pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
Send a "node info" controller operation.
Definition: ipc_controld.c:405
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:433
#define CRM_OP_HELLO
Definition: crm.h:138
#define crm_err(fmt, args...)
Definition: logging.h:381
#define XML_ATTR_REFERENCE
Definition: msg_xml.h:179
#define PCMK__XA_MODE
Definition: crm_internal.h:90
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 XML_ATTR_RESPONSE
Definition: msg_xml.h:176
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:605
#define XML_ATTR_CRM_VERSION
Definition: msg_xml.h:140
#define CRM_OP_INVOKE_LRM
Definition: crm.h:146
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 PCMK__CONTROLD_CMD_NODES
Definition: crm_internal.h:121
#define CRM_OP_PING
Definition: crm.h:133
#define XML_LRM_ATTR_TARGET
Definition: msg_xml.h:308
Daemon&#39;s reply to client IPC request.
Definition: ipc.h:83
#define CRM_OP_LRM_DELETE
Definition: crm.h:148
#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:384
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:548
#define XML_AGENT_ATTR_CLASS
Definition: msg_xml.h:280
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:2510