pacemaker 2.1.1-77db578727
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
ipc_pacemakerd.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 <stdlib.h>
13#include <time.h>
14
15#include <crm/crm.h>
16#include <crm/msg_xml.h>
17#include <crm/common/xml.h>
18#include <crm/common/ipc.h>
21#include "crmcommon_private.h"
22
23typedef struct pacemakerd_api_private_s {
24 enum pcmk_pacemakerd_state state;
25 char *client_uuid;
27
28static const char *pacemakerd_state_str[] = {
35};
36
39{
40 int i;
41
42 if (state == NULL) {
44 }
46 i++) {
47 if (pcmk__str_eq(state, pacemakerd_state_str[i], pcmk__str_none)) {
48 return i;
49 }
50 }
52}
53
54const char *
56 enum pcmk_pacemakerd_state state)
57{
58 if ((state >= pcmk_pacemakerd_state_init) &&
59 (state <= pcmk_pacemakerd_state_max)) {
60 return pacemakerd_state_str[state];
61 }
62 return "invalid";
63}
64
65// \return Standard Pacemaker return code
66static int
67new_data(pcmk_ipc_api_t *api)
68{
69 struct pacemakerd_api_private_s *private = NULL;
70
71 api->api_data = calloc(1, sizeof(struct pacemakerd_api_private_s));
72
73 if (api->api_data == NULL) {
74 return errno;
75 }
76
77 private = api->api_data;
78 private->state = pcmk_pacemakerd_state_invalid;
79 /* other as with cib, controld, ... we are addressing pacemakerd just
80 from the local node -> pid is unique and thus sufficient as an ID
81 */
82 private->client_uuid = pcmk__getpid_s();
83
84 return pcmk_rc_ok;
85}
86
87static void
88free_data(void *data)
89{
90 free(((struct pacemakerd_api_private_s *) data)->client_uuid);
91 free(data);
92}
93
94// \return Standard Pacemaker return code
95static int
96post_connect(pcmk_ipc_api_t *api)
97{
98 struct pacemakerd_api_private_s *private = NULL;
99
100 if (api->api_data == NULL) {
101 return EINVAL;
102 }
103 private = api->api_data;
104 private->state = pcmk_pacemakerd_state_invalid;
105
106 return pcmk_rc_ok;
107}
108
109static void
110post_disconnect(pcmk_ipc_api_t *api)
111{
112 struct pacemakerd_api_private_s *private = NULL;
113
114 if (api->api_data == NULL) {
115 return;
116 }
117 private = api->api_data;
118 private->state = pcmk_pacemakerd_state_invalid;
119
120 return;
121}
122
123static bool
124reply_expected(pcmk_ipc_api_t *api, xmlNode *request)
125{
126 const char *command = crm_element_value(request, F_CRM_TASK);
127
128 if (command == NULL) {
129 return false;
130 }
131
132 // We only need to handle commands that functions in this file can send
133 return pcmk__str_any_of(command, CRM_OP_PING, CRM_OP_QUIT, NULL);
134}
135
136static void
137dispatch(pcmk_ipc_api_t *api, xmlNode *reply)
138{
139 crm_exit_t status = CRM_EX_OK;
140 xmlNode *msg_data = NULL;
141 pcmk_pacemakerd_api_reply_t reply_data = {
143 };
144 const char *value = NULL;
145 long long value_ll = 0;
146
147 if (pcmk__str_eq((const char *) reply->name, "ack", pcmk__str_casei)) {
148 return;
149 }
150
151 value = crm_element_value(reply, F_CRM_MSG_TYPE);
152 if ((value == NULL) || (strcmp(value, XML_ATTR_RESPONSE))) {
153 crm_debug("Unrecognizable pacemakerd message: invalid message type '%s'",
154 crm_str(value));
155 status = CRM_EX_PROTOCOL;
156 goto done;
157 }
158
159 if (crm_element_value(reply, XML_ATTR_REFERENCE) == NULL) {
160 crm_debug("Unrecognizable pacemakerd message: no reference");
161 status = CRM_EX_PROTOCOL;
162 goto done;
163 }
164
165 value = crm_element_value(reply, F_CRM_TASK);
166
167 // Parse useful info from reply
168 msg_data = get_message_xml(reply, F_CRM_DATA);
169 crm_element_value_ll(msg_data, XML_ATTR_TSTAMP, &value_ll);
170
171 if (pcmk__str_eq(value, CRM_OP_PING, pcmk__str_none)) {
173 reply_data.data.ping.state =
176 reply_data.data.ping.status =
177 pcmk__str_eq(crm_element_value(msg_data, XML_PING_ATTR_STATUS), "ok",
179 reply_data.data.ping.last_good = (time_t) value_ll;
180 reply_data.data.ping.sys_from = crm_element_value(msg_data,
182 } else if (pcmk__str_eq(value, CRM_OP_QUIT, pcmk__str_none)) {
184 reply_data.data.shutdown.status = atoi(crm_element_value(msg_data, XML_LRM_ATTR_OPSTATUS));
185 } else {
186 crm_debug("Unrecognizable pacemakerd message: '%s'", crm_str(value));
187 status = CRM_EX_PROTOCOL;
188 goto done;
189 }
190
191done:
192 pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
193}
194
197{
198 pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
199
200 if (cmds != NULL) {
201 cmds->new_data = new_data;
202 cmds->free_data = free_data;
203 cmds->post_connect = post_connect;
204 cmds->reply_expected = reply_expected;
205 cmds->dispatch = dispatch;
206 cmds->post_disconnect = post_disconnect;
207 }
208 return cmds;
209}
210
211static int
212do_pacemakerd_api_call(pcmk_ipc_api_t *api, const char *ipc_name, const char *task)
213{
215 xmlNode *cmd;
216 int rc;
217
218 CRM_CHECK(api != NULL, return -EINVAL);
219 private = api->api_data;
220 CRM_ASSERT(private != NULL);
221
222 cmd = create_request(task, NULL, NULL, CRM_SYSTEM_MCP,
223 ipc_name?ipc_name:((crm_system_name? crm_system_name : "client")),
224 private->client_uuid);
225
226 if (cmd) {
227 rc = pcmk__send_ipc_request(api, cmd);
228 if (rc != pcmk_rc_ok) {
229 crm_debug("Couldn't ping pacemakerd: %s rc=%d",
230 pcmk_rc_str(rc), rc);
231 rc = ECOMM;
232 }
233 free_xml(cmd);
234 } else {
235 rc = ENOMSG;
236 }
237
238 return rc;
239}
240
241int
242pcmk_pacemakerd_api_ping(pcmk_ipc_api_t *api, const char *ipc_name)
243{
244 return do_pacemakerd_api_call(api, ipc_name, CRM_OP_PING);
245}
246
247int
249{
250 return do_pacemakerd_api_call(api, ipc_name, CRM_OP_QUIT);
251}
char data[0]
Definition cpg.c:10
A dumping ground.
#define CRM_SYSTEM_MCP
Definition crm.h:111
#define CRM_OP_QUIT
Definition crm.h:141
#define CRM_OP_PING
Definition crm.h:134
char * crm_system_name
Definition utils.c:54
G_GNUC_INTERNAL int pcmk__send_ipc_request(pcmk_ipc_api_t *api, xmlNode *request)
Definition ipc_client.c:584
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
IPC interface to Pacemaker daemons.
#define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from)
Definition ipc.h:42
@ pcmk_ipc_event_reply
Daemon's reply to client IPC request.
Definition ipc.h:82
pcmk__ipc_methods_t * pcmk__pacemakerd_api_methods()
const char * pcmk_pacemakerd_api_daemon_state_enum2text(enum pcmk_pacemakerd_state state)
int pcmk_pacemakerd_api_shutdown(pcmk_ipc_api_t *api, const char *ipc_name)
struct pacemakerd_api_private_s pacemakerd_api_private_t
enum pcmk_pacemakerd_state pcmk_pacemakerd_api_daemon_state_text2enum(const char *state)
int pcmk_pacemakerd_api_ping(pcmk_ipc_api_t *api, const char *ipc_name)
IPC commands for Pacemakerd.
@ pcmk_pacemakerd_reply_unknown
@ pcmk_pacemakerd_reply_shutdown
@ pcmk_pacemakerd_reply_ping
pcmk_pacemakerd_state
@ pcmk_pacemakerd_state_invalid
@ pcmk_pacemakerd_state_max
@ pcmk_pacemakerd_state_init
#define crm_str(x)
Definition logging.h:376
#define CRM_CHECK(expr, failure_action)
Definition logging.h:218
#define crm_debug(fmt, args...)
Definition logging.h:355
#define XML_PING_ATTR_PACEMAKERDSTATE_WAITPING
Definition msg_xml.h:162
#define XML_PING_ATTR_SYSFROM
Definition msg_xml.h:157
#define XML_PING_ATTR_PACEMAKERDSTATE
Definition msg_xml.h:159
#define XML_PING_ATTR_PACEMAKERDSTATE_SHUTDOWNCOMPLETE
Definition msg_xml.h:165
#define XML_LRM_ATTR_OPSTATUS
Definition msg_xml.h:307
#define XML_PING_ATTR_PACEMAKERDSTATE_SHUTTINGDOWN
Definition msg_xml.h:164
#define XML_PING_ATTR_PACEMAKERDSTATE_STARTINGDAEMONS
Definition msg_xml.h:161
#define F_CRM_MSG_TYPE
Definition msg_xml.h:87
#define XML_PING_ATTR_STATUS
Definition msg_xml.h:156
#define XML_ATTR_RESPONSE
Definition msg_xml.h:149
#define XML_ATTR_REFERENCE
Definition msg_xml.h:153
#define F_CRM_DATA
Definition msg_xml.h:84
#define F_CRM_TASK
Definition msg_xml.h:85
#define XML_ATTR_TSTAMP
Definition msg_xml.h:125
#define XML_PING_ATTR_PACEMAKERDSTATE_RUNNING
Definition msg_xml.h:163
#define XML_PING_ATTR_PACEMAKERDSTATE_INIT
Definition msg_xml.h:160
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition nvpair.c:530
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:598
int rc
Definition pcmk_fence.c:35
#define ECOMM
#define CRM_ASSERT(expr)
Definition results.h:42
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition results.c:420
@ CRM_EX_PROTOCOL
Definition results.h:241
@ CRM_EX_OK
Definition results.h:217
@ pcmk_rc_ok
Definition results.h:142
@ pcmk_rc_error
Definition results.h:138
enum crm_exit_e crm_exit_t
@ pcmk__str_none
@ pcmk__str_casei
bool pcmk__str_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
Definition strings.c:979
int(* new_data)(pcmk_ipc_api_t *api)
void(* free_data)(void *api_data)
void(* post_disconnect)(pcmk_ipc_api_t *api)
void(* dispatch)(pcmk_ipc_api_t *api, xmlNode *msg)
bool(* reply_expected)(pcmk_ipc_api_t *api, xmlNode *request)
int(* post_connect)(pcmk_ipc_api_t *api)
enum pcmk_pacemakerd_api_reply reply_type
struct pcmk_pacemakerd_api_reply_t::@4::@6 shutdown
enum pcmk_pacemakerd_state state
union pcmk_pacemakerd_api_reply_t::@4 data
struct pcmk_pacemakerd_api_reply_t::@4::@5 ping
Wrappers for and extensions to libxml2.
void free_xml(xmlNode *child)
Definition xml.c:823
xmlNode * get_message_xml(xmlNode *msg, const char *field)
Definition messages.c:154