pacemaker 2.1.7-2.1.7
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
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
25struct controld_api_private_s {
26 char *client_uuid;
27 unsigned int replies_expected;
28};
29
38const 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
58static int
59new_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
86static void
87free_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
94static int
95post_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
119static void
120set_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
141static void
142set_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
155static void
156set_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
177static bool
178reply_expected(pcmk_ipc_api_t *api, const xmlNode *request)
179{
180 // We only need to handle commands that API functions can send
189 NULL);
190}
191
192static bool
193dispatch(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
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
272done:
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
309static xmlNode *
310create_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
331static int
332send_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
346static xmlNode *
347create_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
369int
370pcmk_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
404int
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
432int
433pcmk_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
455int
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
471static int
472controller_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
547int
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
580int
581pcmk_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
604unsigned 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
618xmlNode *
619create_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}
char * pcmk__transition_key(int transition_id, int action_id, int target_rc, const char *node)
Definition actions.c:250
bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name)
Definition nvpair.c:905
char * crm_meta_name(const char *field)
Definition utils.c:468
enum crm_ais_msg_types type
Definition cpg.c:3
char data[0]
Definition cpg.c:10
A dumping ground.
#define CRM_SYSTEM_CRMD
Definition crm.h:104
#define CRM_SYSTEM_DC
Definition crm.h:101
#define CRM_OP_HELLO
Definition crm.h:138
#define CRM_OP_REPROBE
Definition crm.h:151
#define CRM_FEATURE_SET
Definition crm.h:70
#define CRM_OP_PING
Definition crm.h:133
#define CRM_OP_LRM_FAIL
Definition crm.h:149
#define CRM_OP_RM_NODE_CACHE
Definition crm.h:154
#define CRM_OP_LRM_DELETE
Definition crm.h:148
#define CRM_OP_NODE_INFO
Definition crm.h:134
char * crm_system_name
Definition utils.c:51
#define CRM_OP_INVOKE_LRM
Definition crm.h:146
#define PCMK__XA_CRMD
#define PCMK__CONTROLD_CMD_NODES
#define PCMK__XA_MODE
#define PCMK__XA_IN_CCM
G_GNUC_INTERNAL int pcmk__send_ipc_request(pcmk_ipc_api_t *api, const xmlNode *request)
Definition ipc_client.c:668
#define PCMK__CONTROLD_API_MINOR
#define PCMK__CONTROLD_API_MAJOR
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
IPC interface to Pacemaker daemons.
#define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from)
Definition ipc.h:43
@ pcmk_ipc_event_reply
Daemon's reply to client IPC request.
Definition ipc.h:83
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
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.
int pcmk_controld_api_list_nodes(pcmk_ipc_api_t *api)
Ask the controller for cluster information.
int pcmk_controld_api_ping(pcmk_ipc_api_t *api, const char *node_name)
Ask the controller for status.
unsigned int pcmk_controld_api_replies_expected(const pcmk_ipc_api_t *api)
Get the number of IPC replies currently expected from the controller.
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.
int pcmk_controld_api_node_info(pcmk_ipc_api_t *api, uint32_t nodeid)
Send a "node info" controller operation.
const char * pcmk__controld_api_reply2str(enum pcmk_controld_api_reply reply)
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.
int pcmk_controld_api_reprobe(pcmk_ipc_api_t *api, const char *target_node, const char *router_node)
Send a reprobe controller operation.
pcmk__ipc_methods_t * pcmk__controld_api_methods(void)
IPC commands for Pacemaker controller.
pcmk_controld_api_reply
Possible types of controller replies.
@ pcmk_controld_reply_nodes
@ pcmk_controld_reply_reprobe
@ pcmk_controld_reply_resource
@ pcmk_controld_reply_ping
@ pcmk_controld_reply_info
@ pcmk_controld_reply_unknown
#define crm_info(fmt, args...)
Definition logging.h:382
#define CRM_XS
Definition logging.h:56
#define crm_debug(fmt, args...)
Definition logging.h:384
#define crm_err(fmt, args...)
Definition logging.h:379
#define crm_trace(fmt, args...)
Definition logging.h:385
#define XML_TAG_CIB
Definition msg_xml.h:137
#define XML_LRM_ATTR_ROUTER_NODE
Definition msg_xml.h:314
#define XML_ATTR_TRANSITION_KEY
Definition msg_xml.h:416
#define XML_ATTR_CRM_VERSION
Definition msg_xml.h:140
#define XML_ATTR_UNAME
Definition msg_xml.h:178
#define XML_PING_ATTR_SYSFROM
Definition msg_xml.h:183
#define XML_ATTR_REQUEST
Definition msg_xml.h:175
#define F_CRM_HOST_FROM
Definition msg_xml.h:118
#define XML_NODE_IS_REMOTE
Definition msg_xml.h:288
#define XML_ATTR_ID
Definition msg_xml.h:156
#define XML_PING_ATTR_CRMDSTATE
Definition msg_xml.h:184
#define XML_ATTR_HAVE_QUORUM
Definition msg_xml.h:145
#define F_CRM_MSG_TYPE
Definition msg_xml.h:115
#define XML_AGENT_ATTR_PROVIDER
Definition msg_xml.h:281
#define XML_AGENT_ATTR_CLASS
Definition msg_xml.h:280
#define XML_TAG_ATTRS
Definition msg_xml.h:229
#define XML_ATTR_ID_LONG
Definition msg_xml.h:159
#define XML_PING_ATTR_STATUS
Definition msg_xml.h:182
#define XML_ATTR_TYPE
Definition msg_xml.h:160
#define XML_ATTR_RESPONSE
Definition msg_xml.h:176
#define XML_LRM_ATTR_TARGET
Definition msg_xml.h:308
#define XML_ATTR_TIMEOUT
Definition msg_xml.h:150
#define XML_ATTR_REFERENCE
Definition msg_xml.h:179
#define F_CRM_DATA
Definition msg_xml.h:112
#define XML_GRAPH_TAG_RSC_OP
Definition msg_xml.h:334
#define F_CRM_TASK
Definition msg_xml.h:113
#define XML_TAG_OPTIONS
Definition msg_xml.h:172
#define XML_ATTR_VERSION
Definition msg_xml.h:154
#define XML_CIB_TAG_NODE
Definition msg_xml.h:223
#define XML_CIB_TAG_RESOURCE
Definition msg_xml.h:235
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:447
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
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
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
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition results.c:501
@ CRM_EX_PROTOCOL
Protocol violated.
Definition results.h:266
@ CRM_EX_OK
Success.
Definition results.h:240
@ pcmk_rc_ok
Definition results.h:154
enum crm_exit_e crm_exit_t
@ pcmk__str_casei
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:957
int(* new_data)(pcmk_ipc_api_t *api)
bool(* reply_expected)(pcmk_ipc_api_t *api, const xmlNode *request)
void(* free_data)(void *api_data)
bool(* dispatch)(pcmk_ipc_api_t *api, xmlNode *msg)
int(* post_connect)(pcmk_ipc_api_t *api)
const char * feature_set
CRM feature set advertised by controller.
struct pcmk_controld_api_reply_t::@1::@3 resource
const char * host_from
Name of node that sent reply.
enum pcmk_controld_api_reply reply_type
union pcmk_controld_api_reply_t::@1 data
Wrappers for and extensions to libxml2.
xmlNode * first_named_child(const xmlNode *parent, const char *name)
Definition xml.c:2484
void crm_xml_set_id(xmlNode *xml, const char *format,...) G_GNUC_PRINTF(2
xmlNode * crm_next_same_xml(const xmlNode *sibling)
Get next instance of same XML tag.
Definition xml.c:2510
void free_xml(xmlNode *child)
Definition xml.c:783
xmlNode * get_message_xml(const xmlNode *msg, const char *field)
Definition messages.c:154
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition xml.c:638