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