This source file includes following definitions.
- client_exit
- client_shutdown
- read_events
- timeout_err
- connection_events
- try_connect
- client_start
- ctl_remote_proxy_cb
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <crm_internal.h>
21
22 #include <glib.h>
23 #include <unistd.h>
24
25 #include <crm/crm.h>
26 #include <crm/msg_xml.h>
27 #include <crm/services.h>
28 #include <crm/common/mainloop.h>
29
30 #include <crm/pengine/status.h>
31 #include <crm/cib.h>
32 #include <crm/lrmd.h>
33
34 extern GHashTable *proxy_table;
35 void lrmd_internal_set_proxy_callback(lrmd_t * lrmd, void *userdata, void (*callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg));
36
37
38 static struct crm_option long_options[] = {
39 {"help", 0, 0, '?'},
40 {"verbose", 0, 0, 'V', "\t\tPrint out logs and events to screen"},
41 {"quiet", 0, 0, 'Q', "\t\tSuppress all output to screen"},
42 {"tls", 1, 0, 'S', "\t\tSet tls host to contact"},
43 {"tls-port", 1, 0, 'p', "\t\tUse custom tls port"},
44 {"node", 1, 0, 'n', "\tNode name to use for ipc proxy"},
45 {"api-call", 1, 0, 'c', "\tDirectly relates to lrmd api functions"},
46 {"-spacer-", 1, 0, '-', "\nParameters for api-call option"},
47 {"action", 1, 0, 'a'},
48 {"rsc-id", 1, 0, 'r'},
49 {"provider", 1, 0, 'P'},
50 {"class", 1, 0, 'C'},
51 {"type", 1, 0, 'T'},
52 {"timeout", 1, 0, 't'},
53 {"param-key", 1, 0, 'k'},
54 {"param-val", 1, 0, 'v'},
55
56 {"-spacer-", 1, 0, '-'},
57 {0, 0, 0, 0}
58 };
59
60
61 static int wait_poke = 0;
62 static int exec_call_id = 0;
63 static gboolean client_start(gpointer user_data);
64 static void try_connect(void);
65
66 static struct {
67 int verbose;
68 int quiet;
69 int print;
70 int interval;
71 int timeout;
72 int port;
73 const char *node_name;
74 const char *api_call;
75 const char *rsc_id;
76 const char *provider;
77 const char *class;
78 const char *type;
79 const char *action;
80 const char *listen;
81 const char *tls_host;
82 lrmd_key_value_t *params;
83 } options;
84
85 GMainLoop *mainloop = NULL;
86 lrmd_t *lrmd_conn = NULL;
87
88 static void
89 client_exit(int rc)
90 {
91 lrmd_api_delete(lrmd_conn);
92 if (proxy_table) {
93 g_hash_table_destroy(proxy_table); proxy_table = NULL;
94 }
95 exit(rc);
96 }
97
98 static void
99 client_shutdown(int nsig)
100 {
101 lrmd_api_delete(lrmd_conn);
102 lrmd_conn = NULL;
103 }
104
105 static void
106 read_events(lrmd_event_data_t * event)
107 {
108 if (wait_poke && event->type == lrmd_event_poke) {
109 client_exit(PCMK_OCF_OK);
110 }
111 if ((event->call_id == exec_call_id) && (event->type == lrmd_event_exec_complete)) {
112 if (event->output) {
113 crm_info("%s", event->output);
114 }
115 if (event->exit_reason) {
116 fprintf(stderr, "%s%s\n", PCMK_OCF_REASON_PREFIX, event->exit_reason);
117 }
118 client_exit(event->rc);
119 }
120 }
121
122 static gboolean
123 timeout_err(gpointer data)
124 {
125 crm_err("timed out in remote_client");
126 client_exit(PCMK_OCF_TIMEOUT);
127
128 return FALSE;
129 }
130
131 static void
132 connection_events(lrmd_event_data_t * event)
133 {
134 int rc = event->connection_rc;
135
136 if (event->type != lrmd_event_connect) {
137
138 return;
139 }
140
141 if (!rc) {
142 client_start(NULL);
143 return;
144 } else {
145 sleep(1);
146 try_connect();
147 }
148 }
149
150 static void
151 try_connect(void)
152 {
153 int tries = 10;
154 static int num_tries = 0;
155 int rc = 0;
156
157 lrmd_conn->cmds->set_callback(lrmd_conn, connection_events);
158 for (; num_tries < tries; num_tries++) {
159 rc = lrmd_conn->cmds->connect_async(lrmd_conn, "lrmd", 10000);
160
161 if (!rc) {
162 num_tries++;
163 return;
164 }
165 sleep(1);
166 }
167
168 crm_err("Failed to connect to pacemaker remote.");
169 client_exit(PCMK_OCF_UNKNOWN_ERROR);
170 }
171
172 static gboolean
173 client_start(gpointer user_data)
174 {
175 int rc = 0;
176
177 if (!lrmd_conn->cmds->is_connected(lrmd_conn)) {
178 try_connect();
179
180 return 0;
181 }
182
183 lrmd_conn->cmds->set_callback(lrmd_conn, read_events);
184
185
186 if (safe_str_eq(options.api_call, "ipc_debug")) {
187
188 return 0;
189 }
190 if (options.timeout) {
191 g_timeout_add(options.timeout, timeout_err, NULL);
192 }
193
194 if (safe_str_eq(options.api_call, "metadata")) {
195 char *output = NULL;
196
197
198
199
200 rc = lrmd_conn->cmds->get_metadata(lrmd_conn,
201 options.class,
202 options.provider, options.type, &output, 0);
203 if (rc == pcmk_ok) {
204 printf("%s", output);
205 free(output);
206 client_exit(PCMK_OCF_OK);
207 }
208 client_exit(PCMK_OCF_UNKNOWN_ERROR);
209
210 } else if (safe_str_eq(options.api_call, "poke")) {
211 rc = lrmd_conn->cmds->poke_connection(lrmd_conn);
212 if (rc != pcmk_ok) {
213 client_exit(PCMK_OCF_UNKNOWN_ERROR);
214 }
215 wait_poke = 1;
216
217 } else {
218 lrmd_rsc_info_t *rsc_info = NULL;
219
220 rsc_info = lrmd_conn->cmds->get_rsc_info(lrmd_conn, options.rsc_id, 0);
221 if (rsc_info == NULL) {
222 rc = lrmd_conn->cmds->register_rsc(lrmd_conn, options.rsc_id,
223 options.class, options.provider, options.type, 0);
224
225 if (rc != 0){
226 crm_err("failed to register resource %s with pacemaker_remote. rc: %d", options.rsc_id, rc);
227 client_exit(1);
228 }
229 }
230 lrmd_free_rsc_info(rsc_info);
231
232 rc = lrmd_conn->cmds->exec(lrmd_conn,
233 options.rsc_id,
234 options.action,
235 NULL,
236 options.interval,
237 options.timeout,
238 0, 0, options.params);
239
240 if (rc > 0) {
241 exec_call_id = rc;
242 } else {
243 crm_err("execution of rsc %s failed. rc = %d", options.rsc_id, rc);
244 client_exit(PCMK_OCF_UNKNOWN_ERROR);
245 }
246 }
247
248 return 0;
249 }
250
251 static void
252 ctl_remote_proxy_cb(lrmd_t *lrmd, void *userdata, xmlNode *msg)
253 {
254 const char *op = crm_element_value(msg, F_LRMD_IPC_OP);
255 const char *session = crm_element_value(msg, F_LRMD_IPC_SESSION);
256
257 if (safe_str_eq(op, LRMD_IPC_OP_NEW)) {
258 const char *channel = crm_element_value(msg, F_LRMD_IPC_IPC_SERVER);
259
260 static struct ipc_client_callbacks proxy_callbacks = {
261 .dispatch = remote_proxy_dispatch,
262 .destroy = remote_proxy_disconnected
263 };
264
265 remote_proxy_new(lrmd, &proxy_callbacks, options.node_name, session, channel);
266
267 } else {
268 remote_proxy_cb(lrmd, options.node_name, msg);
269 }
270 }
271
272 int
273 main(int argc, char **argv)
274 {
275 int option_index = 0;
276 int argerr = 0;
277 int flag;
278 char *key = NULL;
279 char *val = NULL;
280 gboolean use_tls = FALSE;
281 crm_trigger_t *trig;
282
283 crm_set_options(NULL, "mode [options]", long_options,
284 "Inject commands into the lrmd and watch for events\n");
285
286 while (1) {
287 flag = crm_get_option(argc, argv, &option_index);
288 if (flag == -1)
289 break;
290
291 switch (flag) {
292 case '?':
293 crm_help(flag, EX_OK);
294 break;
295 case 'V':
296 options.verbose = 1;
297 break;
298 case 'Q':
299 options.quiet = 1;
300 options.verbose = 0;
301 break;
302 case 'n':
303 options.node_name = optarg;
304 break;
305 case 'c':
306 options.api_call = optarg;
307 break;
308 case 'a':
309 options.action = optarg;
310 break;
311 case 'r':
312 options.rsc_id = optarg;
313 break;
314 case 'P':
315 options.provider = optarg;
316 break;
317 case 'C':
318 options.class = optarg;
319 break;
320 case 'T':
321 options.type = optarg;
322 break;
323 case 't':
324 if(optarg) {
325 options.timeout = atoi(optarg);
326 }
327 break;
328 case 'k':
329 key = optarg;
330 if (key && val) {
331 options.params = lrmd_key_value_add(options.params, key, val);
332 key = val = NULL;
333 }
334 break;
335 case 'v':
336 val = optarg;
337 if (key && val) {
338 options.params = lrmd_key_value_add(options.params, key, val);
339 key = val = NULL;
340 }
341 break;
342 case 'S':
343 options.tls_host = optarg;
344 use_tls = TRUE;
345 break;
346 case 'p':
347 if(optarg) {
348 options.port = atoi(optarg);
349 }
350 use_tls = TRUE;
351 break;
352 default:
353 ++argerr;
354 break;
355 }
356 }
357
358 if (argerr) {
359 crm_help('?', EX_USAGE);
360 }
361 if (optind > argc) {
362 ++argerr;
363 }
364 crm_log_init("remote_client", LOG_INFO, FALSE, options.verbose ? TRUE : FALSE, argc, argv, FALSE);
365
366
367
368 if (!options.api_call ) {
369 crm_err("Nothing to be done. Please specify 'api-call'");
370 return PCMK_OCF_UNKNOWN_ERROR;
371 }
372
373 if (!options.timeout ) {
374 options.timeout = 20000;
375 }
376
377 if (use_tls) {
378 if (options.node_name == NULL) {
379 crm_err("\"node\" option required when tls is in use.");
380 return PCMK_OCF_UNKNOWN_ERROR;
381 }
382 proxy_table =
383 g_hash_table_new_full(crm_strcase_hash, crm_strcase_equal, NULL, remote_proxy_free);
384 lrmd_conn = lrmd_remote_api_new(NULL, options.tls_host ? options.tls_host : "localhost", options.port);
385 lrmd_internal_set_proxy_callback(lrmd_conn, NULL, ctl_remote_proxy_cb);
386 } else {
387 lrmd_conn = lrmd_api_new();
388 }
389 trig = mainloop_add_trigger(G_PRIORITY_HIGH, client_start, NULL);
390 mainloop_set_trigger(trig);
391 mainloop_add_signal(SIGTERM, client_shutdown);
392
393 mainloop = g_main_new(FALSE);
394 g_main_run(mainloop);
395
396 client_exit(0);
397 return 0;
398 }