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