This source file includes following definitions.
- free_rsc_info
- free_deletion_op
- free_recurring_op
- fail_pending_op
- lrm_state_is_local
- lrm_state_create
- remote_proxy_remove_by_node
- find_connected_proxy_by_node
- remote_proxy_disconnect_by_node
- internal_lrm_state_destroy
- lrm_state_reset_tables
- lrm_state_init_local
- lrm_state_destroy_all
- lrm_state_find
- lrm_state_find_or_create
- lrm_state_get_list
- lrm_state_disconnect_only
- lrm_state_disconnect
- lrm_state_is_connected
- lrm_state_poke_connection
- controld_connect_local_executor
- crmd_remote_proxy_new
- crmd_is_proxy_session
- crmd_proxy_send
- crmd_proxy_dispatch
- remote_config_check
- crmd_remote_proxy_cb
- controld_connect_remote_executor
- lrm_state_get_metadata
- lrm_state_cancel
- lrm_state_get_rsc_info
- controld_execute_resource_agent
- lrm_state_register_rsc
- lrm_state_unregister_rsc
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <errno.h>
13
14 #include <crm/crm.h>
15 #include <crm/common/iso8601.h>
16 #include <crm/common/xml.h>
17 #include <crm/pengine/rules.h>
18 #include <crm/pengine/rules_internal.h>
19 #include <crm/lrmd_internal.h>
20
21 #include <pacemaker-internal.h>
22 #include <pacemaker-controld.h>
23
24 static GHashTable *lrm_state_table = NULL;
25 extern GHashTable *proxy_table;
26 int lrmd_internal_proxy_send(lrmd_t * lrmd, xmlNode *msg);
27 void lrmd_internal_set_proxy_callback(lrmd_t * lrmd, void *userdata, void (*callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg));
28
29 static void
30 free_rsc_info(gpointer value)
31 {
32 lrmd_rsc_info_t *rsc_info = value;
33
34 lrmd_free_rsc_info(rsc_info);
35 }
36
37 static void
38 free_deletion_op(gpointer value)
39 {
40 struct pending_deletion_op_s *op = value;
41
42 free(op->rsc);
43 delete_ha_msg_input(op->input);
44 free(op);
45 }
46
47 static void
48 free_recurring_op(gpointer value)
49 {
50 active_op_t *op = value;
51
52 free(op->user_data);
53 free(op->rsc_id);
54 free(op->op_type);
55 free(op->op_key);
56 if (op->params) {
57 g_hash_table_destroy(op->params);
58 }
59 free(op);
60 }
61
62 static gboolean
63 fail_pending_op(gpointer key, gpointer value, gpointer user_data)
64 {
65 lrmd_event_data_t event = { 0, };
66 lrm_state_t *lrm_state = user_data;
67 active_op_t *op = value;
68
69 crm_trace("Pre-emptively failing " PCMK__OP_FMT " on %s (call=%s, %s)",
70 op->rsc_id, op->op_type, op->interval_ms,
71 lrm_state->node_name, (char*)key, op->user_data);
72
73 event.type = lrmd_event_exec_complete;
74 event.rsc_id = op->rsc_id;
75 event.op_type = op->op_type;
76 event.user_data = op->user_data;
77 event.timeout = 0;
78 event.interval_ms = op->interval_ms;
79 lrmd__set_result(&event, PCMK_OCF_UNKNOWN_ERROR, PCMK_EXEC_NOT_CONNECTED,
80 "Action was pending when executor connection was dropped");
81 event.t_run = (unsigned int) op->start_time;
82 event.t_rcchange = (unsigned int) op->start_time;
83
84 event.call_id = op->call_id;
85 event.remote_nodename = lrm_state->node_name;
86 event.params = op->params;
87
88 process_lrm_event(lrm_state, &event, op, NULL);
89 lrmd__reset_result(&event);
90 return TRUE;
91 }
92
93 gboolean
94 lrm_state_is_local(lrm_state_t *lrm_state)
95 {
96 return (lrm_state != NULL)
97 && pcmk__str_eq(lrm_state->node_name, controld_globals.our_nodename,
98 pcmk__str_casei);
99 }
100
101
102
103
104
105
106
107
108
109 static lrm_state_t *
110 lrm_state_create(const char *node_name)
111 {
112 lrm_state_t *state = NULL;
113
114 if (!node_name) {
115 crm_err("No node name given for lrm state object");
116 return NULL;
117 }
118
119 state = pcmk__assert_alloc(1, sizeof(lrm_state_t));
120
121 state->node_name = pcmk__str_copy(node_name);
122 state->rsc_info_cache = pcmk__strkey_table(NULL, free_rsc_info);
123 state->deletion_ops = pcmk__strkey_table(free, free_deletion_op);
124 state->active_ops = pcmk__strkey_table(free, free_recurring_op);
125 state->resource_history = pcmk__strkey_table(NULL, history_free);
126 state->metadata_cache = metadata_cache_new();
127
128 g_hash_table_insert(lrm_state_table, (char *)state->node_name, state);
129 return state;
130 }
131
132 static gboolean
133 remote_proxy_remove_by_node(gpointer key, gpointer value, gpointer user_data)
134 {
135 remote_proxy_t *proxy = value;
136 const char *node_name = user_data;
137
138 if (pcmk__str_eq(node_name, proxy->node_name, pcmk__str_casei)) {
139 return TRUE;
140 }
141
142 return FALSE;
143 }
144
145 static remote_proxy_t *
146 find_connected_proxy_by_node(const char * node_name)
147 {
148 GHashTableIter gIter;
149 remote_proxy_t *proxy = NULL;
150
151 CRM_CHECK(proxy_table != NULL, return NULL);
152
153 g_hash_table_iter_init(&gIter, proxy_table);
154
155 while (g_hash_table_iter_next(&gIter, NULL, (gpointer *) &proxy)) {
156 if (proxy->source
157 && pcmk__str_eq(node_name, proxy->node_name, pcmk__str_casei)) {
158 return proxy;
159 }
160 }
161
162 return NULL;
163 }
164
165 static void
166 remote_proxy_disconnect_by_node(const char * node_name)
167 {
168 remote_proxy_t *proxy = NULL;
169
170 CRM_CHECK(proxy_table != NULL, return);
171
172 while ((proxy = find_connected_proxy_by_node(node_name)) != NULL) {
173
174
175
176 if (proxy->source) {
177 mainloop_del_ipc_client(proxy->source);
178 }
179 }
180
181 return;
182 }
183
184 static void
185 internal_lrm_state_destroy(gpointer data)
186 {
187 lrm_state_t *lrm_state = data;
188
189 if (!lrm_state) {
190 return;
191 }
192
193
194
195
196
197
198 remote_proxy_disconnect_by_node(lrm_state->node_name);
199
200 crm_trace("Destroying proxy table %s with %u members",
201 lrm_state->node_name, g_hash_table_size(proxy_table));
202
203 g_hash_table_foreach_remove(proxy_table, remote_proxy_remove_by_node, (char *) lrm_state->node_name);
204 remote_ra_cleanup(lrm_state);
205 lrmd_api_delete(lrm_state->conn);
206
207 if (lrm_state->rsc_info_cache) {
208 crm_trace("Destroying rsc info cache with %u members",
209 g_hash_table_size(lrm_state->rsc_info_cache));
210 g_hash_table_destroy(lrm_state->rsc_info_cache);
211 }
212 if (lrm_state->resource_history) {
213 crm_trace("Destroying history op cache with %u members",
214 g_hash_table_size(lrm_state->resource_history));
215 g_hash_table_destroy(lrm_state->resource_history);
216 }
217 if (lrm_state->deletion_ops) {
218 crm_trace("Destroying deletion op cache with %u members",
219 g_hash_table_size(lrm_state->deletion_ops));
220 g_hash_table_destroy(lrm_state->deletion_ops);
221 }
222 if (lrm_state->active_ops != NULL) {
223 crm_trace("Destroying pending op cache with %u members",
224 g_hash_table_size(lrm_state->active_ops));
225 g_hash_table_destroy(lrm_state->active_ops);
226 }
227 metadata_cache_free(lrm_state->metadata_cache);
228
229 free((char *)lrm_state->node_name);
230 free(lrm_state);
231 }
232
233 void
234 lrm_state_reset_tables(lrm_state_t * lrm_state, gboolean reset_metadata)
235 {
236 if (lrm_state->resource_history) {
237 crm_trace("Resetting resource history cache with %u members",
238 g_hash_table_size(lrm_state->resource_history));
239 g_hash_table_remove_all(lrm_state->resource_history);
240 }
241 if (lrm_state->deletion_ops) {
242 crm_trace("Resetting deletion operations cache with %u members",
243 g_hash_table_size(lrm_state->deletion_ops));
244 g_hash_table_remove_all(lrm_state->deletion_ops);
245 }
246 if (lrm_state->active_ops != NULL) {
247 crm_trace("Resetting active operations cache with %u members",
248 g_hash_table_size(lrm_state->active_ops));
249 g_hash_table_remove_all(lrm_state->active_ops);
250 }
251 if (lrm_state->rsc_info_cache) {
252 crm_trace("Resetting resource information cache with %u members",
253 g_hash_table_size(lrm_state->rsc_info_cache));
254 g_hash_table_remove_all(lrm_state->rsc_info_cache);
255 }
256 if (reset_metadata) {
257 metadata_cache_reset(lrm_state->metadata_cache);
258 }
259 }
260
261 gboolean
262 lrm_state_init_local(void)
263 {
264 if (lrm_state_table) {
265 return TRUE;
266 }
267
268 lrm_state_table = pcmk__strikey_table(NULL, internal_lrm_state_destroy);
269 if (!lrm_state_table) {
270 return FALSE;
271 }
272
273 proxy_table = pcmk__strikey_table(NULL, remote_proxy_free);
274 if (!proxy_table) {
275 g_hash_table_destroy(lrm_state_table);
276 lrm_state_table = NULL;
277 return FALSE;
278 }
279
280 return TRUE;
281 }
282
283 void
284 lrm_state_destroy_all(void)
285 {
286 if (lrm_state_table) {
287 crm_trace("Destroying state table with %u members",
288 g_hash_table_size(lrm_state_table));
289 g_hash_table_destroy(lrm_state_table); lrm_state_table = NULL;
290 }
291 if(proxy_table) {
292 crm_trace("Destroying proxy table with %u members",
293 g_hash_table_size(proxy_table));
294 g_hash_table_destroy(proxy_table); proxy_table = NULL;
295 }
296 }
297
298 lrm_state_t *
299 lrm_state_find(const char *node_name)
300 {
301 if ((node_name == NULL) || (lrm_state_table == NULL)) {
302 return NULL;
303 }
304 return g_hash_table_lookup(lrm_state_table, node_name);
305 }
306
307 lrm_state_t *
308 lrm_state_find_or_create(const char *node_name)
309 {
310 lrm_state_t *lrm_state;
311
312 CRM_CHECK(lrm_state_table != NULL, return NULL);
313
314 lrm_state = g_hash_table_lookup(lrm_state_table, node_name);
315 if (!lrm_state) {
316 lrm_state = lrm_state_create(node_name);
317 }
318
319 return lrm_state;
320 }
321
322 GList *
323 lrm_state_get_list(void)
324 {
325 if (lrm_state_table == NULL) {
326 return NULL;
327 }
328 return g_hash_table_get_values(lrm_state_table);
329 }
330
331 void
332 lrm_state_disconnect_only(lrm_state_t * lrm_state)
333 {
334 int removed = 0;
335
336 if (!lrm_state->conn) {
337 return;
338 }
339 crm_trace("Disconnecting %s", lrm_state->node_name);
340
341 remote_proxy_disconnect_by_node(lrm_state->node_name);
342
343 ((lrmd_t *) lrm_state->conn)->cmds->disconnect(lrm_state->conn);
344
345 if (!pcmk_is_set(controld_globals.fsa_input_register, R_SHUTDOWN)) {
346 removed = g_hash_table_foreach_remove(lrm_state->active_ops,
347 fail_pending_op, lrm_state);
348 crm_trace("Synthesized %d operation failures for %s", removed, lrm_state->node_name);
349 }
350 }
351
352 void
353 lrm_state_disconnect(lrm_state_t * lrm_state)
354 {
355 if (!lrm_state->conn) {
356 return;
357 }
358
359 lrm_state_disconnect_only(lrm_state);
360
361 lrmd_api_delete(lrm_state->conn);
362 lrm_state->conn = NULL;
363 }
364
365 int
366 lrm_state_is_connected(lrm_state_t * lrm_state)
367 {
368 if (!lrm_state->conn) {
369 return FALSE;
370 }
371 return ((lrmd_t *) lrm_state->conn)->cmds->is_connected(lrm_state->conn);
372 }
373
374 int
375 lrm_state_poke_connection(lrm_state_t * lrm_state)
376 {
377
378 if (!lrm_state->conn) {
379 return -ENOTCONN;
380 }
381 return ((lrmd_t *) lrm_state->conn)->cmds->poke_connection(lrm_state->conn);
382 }
383
384
385 int
386 controld_connect_local_executor(lrm_state_t *lrm_state)
387 {
388 int rc = pcmk_rc_ok;
389
390 if (lrm_state->conn == NULL) {
391 lrmd_t *api = NULL;
392
393 rc = lrmd__new(&api, NULL, NULL, 0);
394 if (rc != pcmk_rc_ok) {
395 return rc;
396 }
397 api->cmds->set_callback(api, lrm_op_callback);
398 lrm_state->conn = api;
399 }
400
401 rc = ((lrmd_t *) lrm_state->conn)->cmds->connect(lrm_state->conn,
402 CRM_SYSTEM_CRMD, NULL);
403 rc = pcmk_legacy2rc(rc);
404
405 if (rc == pcmk_rc_ok) {
406 lrm_state->num_lrm_register_fails = 0;
407 } else {
408 lrm_state->num_lrm_register_fails++;
409 }
410 return rc;
411 }
412
413 static remote_proxy_t *
414 crmd_remote_proxy_new(lrmd_t *lrmd, const char *node_name, const char *session_id, const char *channel)
415 {
416 struct ipc_client_callbacks proxy_callbacks = {
417 .dispatch = remote_proxy_dispatch,
418 .destroy = remote_proxy_disconnected
419 };
420 remote_proxy_t *proxy = remote_proxy_new(lrmd, &proxy_callbacks, node_name,
421 session_id, channel);
422 return proxy;
423 }
424
425 gboolean
426 crmd_is_proxy_session(const char *session)
427 {
428 return g_hash_table_lookup(proxy_table, session) ? TRUE : FALSE;
429 }
430
431 void
432 crmd_proxy_send(const char *session, xmlNode *msg)
433 {
434 remote_proxy_t *proxy = g_hash_table_lookup(proxy_table, session);
435 lrm_state_t *lrm_state = NULL;
436
437 if (!proxy) {
438 return;
439 }
440 crm_log_xml_trace(msg, "to-proxy");
441 lrm_state = lrm_state_find(proxy->node_name);
442 if (lrm_state) {
443 crm_trace("Sending event to %.8s on %s", proxy->session_id, proxy->node_name);
444 remote_proxy_relay_event(proxy, msg);
445 }
446 }
447
448 static void
449 crmd_proxy_dispatch(const char *session, xmlNode *msg)
450 {
451 crm_trace("Processing proxied IPC message from session %s", session);
452 crm_log_xml_trace(msg, "controller[inbound]");
453 crm_xml_add(msg, PCMK__XA_CRM_SYS_FROM, session);
454 if (controld_authorize_ipc_message(msg, NULL, session)) {
455 route_message(C_IPC_MESSAGE, msg);
456 }
457 controld_trigger_fsa();
458 }
459
460 static void
461 remote_config_check(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
462 {
463 if (rc != pcmk_ok) {
464 crm_err("Query resulted in an error: %s", pcmk_strerror(rc));
465
466 if (rc == -EACCES || rc == -pcmk_err_schema_validation) {
467 crm_err("The cluster is mis-configured - shutting down and staying down");
468 }
469
470 } else {
471 lrmd_t * lrmd = (lrmd_t *)user_data;
472 crm_time_t *now = crm_time_new(NULL);
473 GHashTable *config_hash = pcmk__strkey_table(free, free);
474
475 crm_debug("Call %d : Parsing CIB options", call_id);
476
477 pe_unpack_nvpairs(output, output, PCMK_XE_CLUSTER_PROPERTY_SET, NULL,
478 config_hash, PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS, FALSE,
479 now, NULL);
480
481
482 lrmd__validate_remote_settings(lrmd, config_hash);
483
484 g_hash_table_destroy(config_hash);
485 crm_time_free(now);
486 }
487 }
488
489 static void
490 crmd_remote_proxy_cb(lrmd_t *lrmd, void *userdata, xmlNode *msg)
491 {
492 lrm_state_t *lrm_state = userdata;
493 const char *session = crm_element_value(msg, PCMK__XA_LRMD_IPC_SESSION);
494 remote_proxy_t *proxy = g_hash_table_lookup(proxy_table, session);
495
496 const char *op = crm_element_value(msg, PCMK__XA_LRMD_IPC_OP);
497 if (pcmk__str_eq(op, LRMD_IPC_OP_NEW, pcmk__str_casei)) {
498 const char *channel = crm_element_value(msg, PCMK__XA_LRMD_IPC_SERVER);
499
500 proxy = crmd_remote_proxy_new(lrmd, lrm_state->node_name, session, channel);
501 if (!remote_ra_controlling_guest(lrm_state)) {
502 if (proxy != NULL) {
503 cib_t *cib_conn = controld_globals.cib_conn;
504
505
506
507
508 int rc = cib_conn->cmds->query(cib_conn, PCMK_XE_CRM_CONFIG,
509 NULL, cib_scope_local);
510 cib_conn->cmds->register_callback_full(cib_conn, rc, 10, FALSE,
511 lrmd,
512 "remote_config_check",
513 remote_config_check,
514 NULL);
515 }
516 } else {
517 crm_debug("Skipping remote_config_check for guest-nodes");
518 }
519
520 } else if (pcmk__str_eq(op, LRMD_IPC_OP_SHUTDOWN_REQ, pcmk__str_casei)) {
521 char *now_s = NULL;
522
523 crm_notice("%s requested shutdown of its remote connection",
524 lrm_state->node_name);
525
526 if (!remote_ra_is_in_maintenance(lrm_state)) {
527 now_s = pcmk__ttoa(time(NULL));
528 update_attrd(lrm_state->node_name, PCMK__NODE_ATTR_SHUTDOWN, now_s,
529 NULL, TRUE);
530 free(now_s);
531
532 remote_proxy_ack_shutdown(lrmd);
533
534 crm_warn("Reconnection attempts to %s may result in failures that must be cleared",
535 lrm_state->node_name);
536 } else {
537 remote_proxy_nack_shutdown(lrmd);
538
539 crm_notice("Remote resource for %s is not managed so no ordered shutdown happening",
540 lrm_state->node_name);
541 }
542 return;
543
544 } else if (pcmk__str_eq(op, LRMD_IPC_OP_REQUEST, pcmk__str_casei) && proxy && proxy->is_local) {
545
546
547
548 int flags = 0;
549 xmlNode *wrapper = pcmk__xe_first_child(msg, PCMK__XE_LRMD_IPC_MSG,
550 NULL, NULL);
551 xmlNode *request = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
552
553 CRM_CHECK(request != NULL, return);
554 CRM_CHECK(lrm_state->node_name, return);
555 crm_xml_add(request, PCMK_XE_ACL_ROLE, "pacemaker-remote");
556 pcmk__update_acl_user(request, PCMK__XA_LRMD_IPC_USER,
557 lrm_state->node_name);
558
559
560
561
562
563
564 if (pcmk__str_eq(crm_element_value(request, PCMK__XA_CRM_TASK),
565 CRM_OP_NODE_INFO, pcmk__str_none)) {
566 int node_id = 0;
567
568 crm_element_value_int(request, PCMK_XA_ID, &node_id);
569 if ((node_id <= 0)
570 && (crm_element_value(request, PCMK_XA_UNAME) == NULL)) {
571 crm_xml_add(request, PCMK_XA_UNAME, lrm_state->node_name);
572 }
573 }
574
575 crmd_proxy_dispatch(session, request);
576
577 crm_element_value_int(msg, PCMK__XA_LRMD_IPC_MSG_FLAGS, &flags);
578 if (flags & crm_ipc_client_response) {
579 int msg_id = 0;
580 xmlNode *op_reply = pcmk__xe_create(NULL, PCMK__XE_ACK);
581
582 crm_xml_add(op_reply, PCMK_XA_FUNCTION, __func__);
583 crm_xml_add_int(op_reply, PCMK__XA_LINE, __LINE__);
584
585 crm_element_value_int(msg, PCMK__XA_LRMD_IPC_MSG_ID, &msg_id);
586 remote_proxy_relay_response(proxy, op_reply, msg_id);
587
588 free_xml(op_reply);
589 }
590
591 } else {
592 remote_proxy_cb(lrmd, lrm_state->node_name, msg);
593 }
594 }
595
596
597
598 int
599 controld_connect_remote_executor(lrm_state_t *lrm_state, const char *server,
600 int port, int timeout_ms)
601 {
602 int rc = pcmk_rc_ok;
603
604 if (lrm_state->conn == NULL) {
605 lrmd_t *api = NULL;
606
607 rc = lrmd__new(&api, lrm_state->node_name, server, port);
608 if (rc != pcmk_rc_ok) {
609 crm_warn("Pacemaker Remote connection to %s:%s failed: %s "
610 CRM_XS " rc=%d", server, port, pcmk_rc_str(rc), rc);
611
612 return rc;
613 }
614 lrm_state->conn = api;
615 api->cmds->set_callback(api, remote_lrm_op_callback);
616 lrmd_internal_set_proxy_callback(api, lrm_state, crmd_remote_proxy_cb);
617 }
618
619 crm_trace("Initiating remote connection to %s:%d with timeout %dms",
620 server, port, timeout_ms);
621 rc = ((lrmd_t *) lrm_state->conn)->cmds->connect_async(lrm_state->conn,
622 lrm_state->node_name,
623 timeout_ms);
624 if (rc == pcmk_ok) {
625 lrm_state->num_lrm_register_fails = 0;
626 } else {
627 lrm_state->num_lrm_register_fails++;
628 }
629 return pcmk_legacy2rc(rc);
630 }
631
632 int
633 lrm_state_get_metadata(lrm_state_t * lrm_state,
634 const char *class,
635 const char *provider,
636 const char *agent, char **output, enum lrmd_call_options options)
637 {
638 lrmd_key_value_t *params = NULL;
639
640 if (!lrm_state->conn) {
641 return -ENOTCONN;
642 }
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658 params = lrmd_key_value_add(params, CRM_META "_" PCMK__META_ON_NODE,
659 lrm_state->node_name);
660
661 return ((lrmd_t *) lrm_state->conn)->cmds->get_metadata_params(lrm_state->conn,
662 class, provider, agent, output, options, params);
663 }
664
665 int
666 lrm_state_cancel(lrm_state_t *lrm_state, const char *rsc_id, const char *action,
667 guint interval_ms)
668 {
669 if (!lrm_state->conn) {
670 return -ENOTCONN;
671 }
672
673
674
675 if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
676 return remote_ra_cancel(lrm_state, rsc_id, action, interval_ms);
677 }
678 return ((lrmd_t *) lrm_state->conn)->cmds->cancel(lrm_state->conn, rsc_id,
679 action, interval_ms);
680 }
681
682 lrmd_rsc_info_t *
683 lrm_state_get_rsc_info(lrm_state_t * lrm_state, const char *rsc_id, enum lrmd_call_options options)
684 {
685 lrmd_rsc_info_t *rsc = NULL;
686
687 if (!lrm_state->conn) {
688 return NULL;
689 }
690 if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
691 return remote_ra_get_rsc_info(lrm_state, rsc_id);
692 }
693
694 rsc = g_hash_table_lookup(lrm_state->rsc_info_cache, rsc_id);
695 if (rsc == NULL) {
696
697 rsc = ((lrmd_t *) lrm_state->conn)->cmds->get_rsc_info(lrm_state->conn, rsc_id, options);
698 if (rsc == NULL) {
699 return NULL;
700 }
701
702 g_hash_table_insert(lrm_state->rsc_info_cache, rsc->id, rsc);
703 }
704
705 return lrmd_copy_rsc_info(rsc);
706
707 }
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725 int
726 controld_execute_resource_agent(lrm_state_t *lrm_state, const char *rsc_id,
727 const char *action, const char *userdata,
728 guint interval_ms, int timeout_ms,
729 int start_delay_ms, GHashTable *parameters,
730 int *call_id)
731 {
732 int rc = pcmk_rc_ok;
733 lrmd_key_value_t *params = NULL;
734
735 if (lrm_state->conn == NULL) {
736 return ENOTCONN;
737 }
738
739
740 if (parameters != NULL) {
741 const char *key = NULL;
742 const char *value = NULL;
743 GHashTableIter iter;
744
745 g_hash_table_iter_init(&iter, parameters);
746 while (g_hash_table_iter_next(&iter, (gpointer *) &key,
747 (gpointer *) &value)) {
748 params = lrmd_key_value_add(params, key, value);
749 }
750 }
751
752 if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
753 rc = controld_execute_remote_agent(lrm_state, rsc_id, action,
754 userdata, interval_ms, timeout_ms,
755 start_delay_ms, params, call_id);
756
757 } else {
758 rc = ((lrmd_t *) lrm_state->conn)->cmds->exec(lrm_state->conn, rsc_id,
759 action, userdata,
760 interval_ms, timeout_ms,
761 start_delay_ms,
762 lrmd_opt_notify_changes_only,
763 params);
764 if (rc < 0) {
765 rc = pcmk_legacy2rc(rc);
766 } else {
767 *call_id = rc;
768 rc = pcmk_rc_ok;
769 }
770 }
771 return rc;
772 }
773
774 int
775 lrm_state_register_rsc(lrm_state_t * lrm_state,
776 const char *rsc_id,
777 const char *class,
778 const char *provider, const char *agent, enum lrmd_call_options options)
779 {
780 lrmd_t *conn = (lrmd_t *) lrm_state->conn;
781
782 if (conn == NULL) {
783 return -ENOTCONN;
784 }
785
786 if (is_remote_lrmd_ra(agent, provider, NULL)) {
787 return lrm_state_find_or_create(rsc_id)? pcmk_ok : -EINVAL;
788 }
789
790
791
792
793 return conn->cmds->register_rsc(lrm_state->conn, rsc_id, class, provider,
794 agent, options);
795 }
796
797 int
798 lrm_state_unregister_rsc(lrm_state_t * lrm_state,
799 const char *rsc_id, enum lrmd_call_options options)
800 {
801 if (!lrm_state->conn) {
802 return -ENOTCONN;
803 }
804
805 if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
806 g_hash_table_remove(lrm_state_table, rsc_id);
807 return pcmk_ok;
808 }
809
810 g_hash_table_remove(lrm_state->rsc_info_cache, rsc_id);
811
812
813
814
815
816
817 return ((lrmd_t *) lrm_state->conn)->cmds->unregister_rsc(lrm_state->conn, rsc_id, options);
818 }