This source file includes following definitions.
- mock_based_ipc_accept
- mock_based_ipc_closed
- mock_based_ipc_destroy
- mock_based_handle_query
- mock_based_common_callback_worker
- mock_based_dispatch_command
- mock_based_register_module
- mock_based_options
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <crm_internal.h>
25 #if 0
26 #include "crm/common/ipc_internal.h"
27 #include "crm/common/xml.h"
28 #endif
29 #include "crm/msg_xml.h"
30 #include "daemons/based/pacemaker-based.h"
31
32 #include <qb/qbipcs.h>
33
34 #include "based.h"
35
36
37
38
39 mock_based_context_t mock_based_context;
40
41
42
43 static int32_t
44 mock_based_ipc_accept(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
45 {
46 int32_t ret = 0;
47 pcmk__client_t *cib_client;
48
49 crm_trace("Connection %p", c);
50 cib_client = pcmk__new_client(c, uid, gid);
51 if (cib_client == NULL) {
52 ret = -EIO;
53 }
54
55 cib_client->userdata = &mock_based_context;
56
57 return ret;
58 }
59
60
61 static int32_t
62 mock_based_ipc_closed(qb_ipcs_connection_t *c)
63 {
64 pcmk__client_t *client = pcmk__find_client(c);
65
66 if (client != NULL) {
67 crm_trace("Connection %p", c);
68 pcmk__free_client(client);
69 }
70
71 return 0;
72 }
73
74
75 static void
76 mock_based_ipc_destroy(qb_ipcs_connection_t *c)
77 {
78 crm_trace("Connection %p", c);
79 mock_based_ipc_closed(c);
80 }
81
82
83 static void
84 mock_based_handle_query(pcmk__client_t *cib_client, uint32_t flags,
85 const xmlNode *op_request)
86 {
87 xmlNode *reply, *cib;
88 const char cib_str[] =
89 #if 0
90 "<cib/>";
91 #else
92 "<cib validate-with='pacemaker-1.2' admin_epoch='0' epoch='0' num_updates='0'>"\
93 " <configuration>"\
94 " <crm_config/>"\
95 " <nodes/>"\
96 " <resources/>"\
97 " <constraints/>"\
98 " </configuration>"\
99 " <status/>"\
100 "</cib>";
101 #endif
102 cib = xmlReadMemory(cib_str, sizeof(cib_str), "file:///tmp/foo", NULL, 0)->children;
103
104 reply = create_xml_node(NULL, "cib-reply");
105 crm_xml_add(reply, F_TYPE, T_CIB);
106 crm_xml_add(reply, F_CIB_OPERATION,
107 crm_element_value(op_request, F_CIB_OPERATION));
108 crm_xml_add(reply, F_CIB_CALLID,
109 crm_element_value(op_request, F_CIB_CALLID));
110 crm_xml_add(reply, F_CIB_CLIENTID,
111 crm_element_value(op_request, F_CIB_CLIENTID));
112 crm_xml_add_int(reply, F_CIB_CALLOPTS, flags);
113 crm_xml_add_int(reply, F_CIB_RC, pcmk_ok);
114
115 if (cib != NULL) {
116 crm_trace("Attaching reply output");
117 add_message_xml(reply, F_CIB_CALLDATA, cib);
118 }
119
120 pcmk__ipc_send_xml(cib_client, cib_client->request_id, reply,
121 ((flags & cib_sync_call)? crm_ipc_flags_none
122 : crm_ipc_server_event));
123
124 free_xml(reply);
125 free_xml(cib);
126 }
127
128
129 static void
130 mock_based_common_callback_worker(uint32_t id, uint32_t flags,
131 xmlNode *op_request,
132 pcmk__client_t *cib_client)
133 {
134 const char *op = crm_element_value(op_request, F_CIB_OPERATION);
135 mock_based_context_t *ctxt;
136
137 if (!strcmp(op, CRM_OP_REGISTER)) {
138 if (flags & crm_ipc_client_response) {
139 xmlNode *ack = create_xml_node(NULL, __func__);
140 crm_xml_add(ack, F_CIB_OPERATION, CRM_OP_REGISTER);
141 crm_xml_add(ack, F_CIB_CLIENTID, cib_client->id);
142 pcmk__ipc_send_xml(cib_client, id, ack, flags);
143 cib_client->request_id = 0;
144 free_xml(ack);
145 }
146
147 } else if (!strcmp(op, T_CIB_NOTIFY)) {
148 int on_off = 0;
149 const char *type = crm_element_value(op_request, F_CIB_NOTIFY_TYPE);
150 crm_element_value_int(op_request, F_CIB_NOTIFY_ACTIVATE, &on_off);
151
152 crm_debug("Setting %s callbacks for %s (%s): %s",
153 type, cib_client->name, cib_client->id, on_off ? "on" : "off");
154
155 if (!strcmp(type, T_CIB_DIFF_NOTIFY) && on_off) {
156 pcmk__set_client_flags(cib_client, cib_notify_diff);
157 }
158
159 ctxt = (mock_based_context_t *) cib_client->userdata;
160 for (size_t c = ctxt->modules_cnt; c > 0; c--) {
161 if (ctxt->modules[c - 1]->hooks.cib_notify != NULL) {
162 ctxt->modules[c - 1]->hooks.cib_notify(cib_client);
163 }
164 }
165
166 if (flags & crm_ipc_client_response) {
167 pcmk__ipc_send_ack(cib_client, id, flags, "ack", CRM_EX_OK);
168 }
169
170 } else if (!strcmp(op, CIB_OP_QUERY)) {
171 mock_based_handle_query(cib_client, flags, op_request);
172
173 } else {
174 crm_notice("Discarded request %s", op);
175 }
176 }
177
178
179 static int32_t
180 mock_based_dispatch_command(qb_ipcs_connection_t *c, void *data, size_t size)
181 {
182 uint32_t id = 0, flags = 0;
183 int call_options = 0;
184 pcmk__client_t *cib_client = pcmk__find_client(c);
185 xmlNode *op_request = pcmk__client_data2xml(cib_client, data, &id, &flags);
186
187 crm_notice("Got connection %p", c);
188 assert(op_request != NULL);
189
190 if (cib_client == NULL || op_request == NULL) {
191 if (op_request == NULL) {
192 crm_trace("Invalid message from %p", c);
193 pcmk__ipc_send_ack(cib_client, id, flags, "nack", CRM_EX_PROTOCOL);
194 }
195 return 0;
196 }
197
198 crm_element_value_int(op_request, F_CIB_CALLOPTS, &call_options);
199 if (call_options & cib_sync_call) {
200 assert(flags & crm_ipc_client_response);
201 cib_client->request_id = id;
202 }
203
204 assert(cib_client->name == NULL);
205 crm_element_value_int(op_request, F_CIB_CALLOPTS, &call_options);
206 crm_xml_add(op_request, F_CIB_CLIENTID, cib_client->id);
207 crm_xml_add(op_request, F_CIB_CLIENTNAME, cib_client->name);
208
209 mock_based_common_callback_worker(id, flags, op_request, cib_client);
210 free_xml(op_request);
211
212 return 0;
213 }
214
215
216
217 size_t mock_based_register_module(module_t mod) {
218 module_t *module;
219 size_t ret = mock_based_context.modules_cnt++;
220
221 mock_based_context.modules = realloc(mock_based_context.modules,
222 sizeof(*mock_based_context.modules)
223 * mock_based_context.modules_cnt);
224 if (mock_based_context.modules == NULL
225 || (module = malloc(sizeof(module_t))) == NULL) {
226 abort();
227 }
228
229 memcpy(module, &mod, sizeof(mod));
230 mock_based_context.modules[mock_based_context.modules_cnt - 1] = module;
231
232 return ret;
233 }
234
235 static int
236 mock_based_options(mock_based_context_t *ctxt,
237 bool usage, int argc, const char *argv[])
238 {
239 const char **args2argv;
240 char *s;
241 int ret = 0;
242
243 if (argc <= 1) {
244 const char *help_argv[] = {argv[0], "-h"};
245 return mock_based_options(ctxt, false, 2, (const char **) &help_argv);
246 }
247
248 for (size_t i = 1; i < argc; i++) {
249 if (argv[i][0] == '-' && argv[i][1] != '-' && argv[i][1] != '\0') {
250 if (usage) {
251 printf("\t-%c\t", argv[i][1]);
252 }
253 switch(argv[i][1]) {
254 case 'h':
255 if (usage) {
256 printf("show this help message\n");
257 ret = 1;
258
259 } else {
260 if ((args2argv
261 = malloc((ctxt->modules_cnt + 2) * sizeof(*args2argv))) == NULL
262 || (s
263 = malloc((ctxt->modules_cnt * 2 + 2) * sizeof(*s))) == NULL) {
264 return -1;
265 }
266 s[0] = 'h';
267 args2argv[ctxt->modules_cnt + 1] = (char[]){'-', 'h', '\0'};
268 for (size_t c = ctxt->modules_cnt; c > 0; c--) {
269 args2argv[c] = (char[]){'-', ctxt->modules[c - 1]->shortopt, '\0'};
270 s[(ctxt->modules_cnt - i) + 1] = '|';
271 s[(ctxt->modules_cnt - i) + 2] = ctxt->modules[c - 1]->shortopt;
272 }
273 s[ctxt->modules_cnt * 2 + 1] = '\0';
274 printf("Usage: %s [-{%s}]\n", argv[0], s);
275 (void) mock_based_options(ctxt, true, 2 + ctxt->modules_cnt, args2argv);
276 free(args2argv);
277 free(s);
278 }
279 return ret;
280 default:
281 for (size_t c = ctxt->modules_cnt; c > 0; c--) {
282 if (ctxt->modules[c - 1]->shortopt == argv[i][1]) {
283 ret = ctxt->modules[c - 1]->hooks.argparse(ctxt, usage, argc - i, &argv[i]);
284 if (ret < 0) {
285 break;
286 } else if (ret > 1) {
287 i += (ret - 1);
288 }
289 }
290 }
291 if (ret == 0) {
292 printf("uknown option \"%s\"\n", argv[i]);
293 }
294 break;
295 }
296 }
297 }
298 return ret;
299 }
300
301 int main(int argc, char *argv[])
302 {
303 mock_based_context_t *ctxt = &mock_based_context;
304
305 if (mock_based_options(ctxt, false, argc, (const char **) argv) > 0) {
306 struct qb_ipcs_service_handlers cib_ipc_callbacks = {
307 .connection_accept = mock_based_ipc_accept,
308 .connection_created = NULL,
309 .msg_process = mock_based_dispatch_command,
310 .connection_closed = mock_based_ipc_closed,
311 .connection_destroyed = mock_based_ipc_destroy,
312 };
313 crm_log_preinit(NULL, argc, argv);
314 crm_log_init(NULL, LOG_DEBUG, false, true, argc, argv, false);
315 qb_ipcs_service_t *ipcs_command =
316 mainloop_add_ipc_server(PCMK__SERVER_BASED_RW, QB_IPC_NATIVE,
317 &cib_ipc_callbacks);
318 g_main_loop_run(g_main_loop_new(NULL, false));
319 qb_ipcs_destroy(ipcs_command);
320 }
321
322 for (size_t c = ctxt->modules_cnt; c > 0; c--) {
323 if (ctxt->modules[c - 1]->hooks.destroy != NULL) {
324 ctxt->modules[c - 1]->hooks.destroy(ctxt->modules[c - 1]);
325 }
326 free(mock_based_context.modules[c - 1]);
327 }
328
329 free(mock_based_context.modules);
330 }