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