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