This source file includes following definitions.
- pcmk_pacemakerd_api_daemon_state_text2enum
- pcmk_pacemakerd_api_daemon_state_enum2text
- new_data
- free_data
- post_connect
- post_disconnect
- reply_expected
- dispatch
- pcmk__pacemakerd_api_methods
- pcmk_pacemakerd_api_ping
1
2
3
4
5
6
7
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>
19 #include <crm/common/ipc_internal.h>
20 #include <crm/common/ipc_pacemakerd.h>
21 #include "crmcommon_private.h"
22
23 typedef struct pacemakerd_api_private_s {
24 enum pcmk_pacemakerd_state state;
25 char *client_uuid;
26 } pacemakerd_api_private_t;
27
28 static const char *pacemakerd_state_str[] = {
29 XML_PING_ATTR_PACEMAKERDSTATE_INIT,
30 XML_PING_ATTR_PACEMAKERDSTATE_STARTINGDAEMONS,
31 XML_PING_ATTR_PACEMAKERDSTATE_WAITPING,
32 XML_PING_ATTR_PACEMAKERDSTATE_RUNNING,
33 XML_PING_ATTR_PACEMAKERDSTATE_SHUTTINGDOWN,
34 XML_PING_ATTR_PACEMAKERDSTATE_SHUTDOWNCOMPLETE
35 };
36
37 enum pcmk_pacemakerd_state
38 pcmk_pacemakerd_api_daemon_state_text2enum(const char *state)
39 {
40 int i;
41
42 if (state == NULL) {
43 return pcmk_pacemakerd_state_invalid;
44 }
45 for (i=pcmk_pacemakerd_state_init; i <= pcmk_pacemakerd_state_max;
46 i++) {
47 if (pcmk__str_eq(state, pacemakerd_state_str[i], pcmk__str_none)) {
48 return i;
49 }
50 }
51 return pcmk_pacemakerd_state_invalid;
52 }
53
54 const char *
55 pcmk_pacemakerd_api_daemon_state_enum2text(
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
66 static int
67 new_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
80
81
82 private->client_uuid = pcmk__getpid_s();
83
84 return pcmk_rc_ok;
85 }
86
87 static void
88 free_data(void *data)
89 {
90 free(((struct pacemakerd_api_private_s *) data)->client_uuid);
91 free(data);
92 }
93
94
95 static int
96 post_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
109 static void
110 post_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
123 static bool
124 reply_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
133 return !strcmp(command, CRM_OP_PING);
134 }
135
136 static void
137 dispatch(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 = {
142 pcmk_pacemakerd_reply_unknown
143 };
144 const char *value = NULL;
145 long long value_ll = 0;
146
147 value = crm_element_value(reply, F_CRM_MSG_TYPE);
148 if ((value == NULL) || (strcmp(value, XML_ATTR_RESPONSE))) {
149 crm_debug("Unrecognizable pacemakerd message: invalid message type '%s'",
150 crm_str(value));
151 status = CRM_EX_PROTOCOL;
152 goto done;
153 }
154
155 if (crm_element_value(reply, XML_ATTR_REFERENCE) == NULL) {
156 crm_debug("Unrecognizable pacemakerd message: no reference");
157 status = CRM_EX_PROTOCOL;
158 goto done;
159 }
160
161 value = crm_element_value(reply, F_CRM_TASK);
162 if ((value == NULL) || strcmp(value, CRM_OP_PING)) {
163 crm_debug("Unrecognizable pacemakerd message: '%s'", crm_str(value));
164 status = CRM_EX_PROTOCOL;
165 goto done;
166 }
167
168
169
170 msg_data = get_message_xml(reply, F_CRM_DATA);
171 crm_element_value_ll(msg_data, XML_ATTR_TSTAMP, &value_ll);
172
173 reply_data.reply_type = pcmk_pacemakerd_reply_ping;
174 reply_data.data.ping.state =
175 pcmk_pacemakerd_api_daemon_state_text2enum(
176 crm_element_value(msg_data, XML_PING_ATTR_PACEMAKERDSTATE));
177 reply_data.data.ping.status =
178 pcmk__str_eq(crm_element_value(msg_data, XML_PING_ATTR_STATUS), "ok",
179 pcmk__str_casei)?pcmk_rc_ok:pcmk_rc_error;
180 reply_data.data.ping.last_good = (time_t) value_ll;
181 reply_data.data.ping.sys_from = crm_element_value(msg_data,
182 XML_PING_ATTR_SYSFROM);
183
184 done:
185 pcmk__call_ipc_callback(api, pcmk_ipc_event_reply, status, &reply_data);
186 }
187
188 pcmk__ipc_methods_t *
189 pcmk__pacemakerd_api_methods()
190 {
191 pcmk__ipc_methods_t *cmds = calloc(1, sizeof(pcmk__ipc_methods_t));
192
193 if (cmds != NULL) {
194 cmds->new_data = new_data;
195 cmds->free_data = free_data;
196 cmds->post_connect = post_connect;
197 cmds->reply_expected = reply_expected;
198 cmds->dispatch = dispatch;
199 cmds->post_disconnect = post_disconnect;
200 }
201 return cmds;
202 }
203
204 int
205 pcmk_pacemakerd_api_ping(pcmk_ipc_api_t *api, const char *ipc_name)
206 {
207 pacemakerd_api_private_t *private;
208 xmlNode *cmd;
209 int rc;
210
211 CRM_CHECK(api != NULL, return -EINVAL);
212 private = api->api_data;
213 CRM_ASSERT(private != NULL);
214
215 cmd = create_request(CRM_OP_PING, NULL, NULL, CRM_SYSTEM_MCP,
216 ipc_name?ipc_name:((crm_system_name? crm_system_name : "client")),
217 private->client_uuid);
218
219 if (cmd) {
220 rc = pcmk__send_ipc_request(api, cmd);
221 if (rc != pcmk_rc_ok) {
222 crm_debug("Couldn't ping pacemakerd: %s rc=%d",
223 pcmk_rc_str(rc), rc);
224 rc = ECOMM;
225 }
226 free_xml(cmd);
227 } else {
228 rc = ENOMSG;
229 }
230
231 return rc;
232 }