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
- lrm_state_ipc_connect
- crmd_remote_proxy_new
- crmd_is_proxy_session
- crmd_proxy_send
- crmd_proxy_dispatch
- remote_config_check
- crmd_remote_proxy_cb
- lrm_state_remote_connect_async
- lrm_state_get_metadata
- lrm_state_cancel
- lrm_state_get_rsc_info
- lrm_state_exec
- lrm_state_register_rsc
- lrm_state_unregister_rsc
- crmd_unpack_alerts
- crmd_alert_node_event
- crmd_alert_fencing_op
- crmd_alert_resource_op
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/crm.h>
12 #include <crm/msg_xml.h>
13 #include <crm/common/iso8601.h>
14 #include <crm/pengine/rules.h>
15 #include <crm/pengine/rules_internal.h>
16 #include <crm/lrmd_internal.h>
17
18 #include <pacemaker-internal.h>
19 #include <pacemaker-controld.h>
20
21 GHashTable *lrm_state_table = NULL;
22 extern GHashTable *proxy_table;
23 int lrmd_internal_proxy_send(lrmd_t * lrmd, xmlNode *msg);
24 void lrmd_internal_set_proxy_callback(lrmd_t * lrmd, void *userdata, void (*callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg));
25
26 static void
27 free_rsc_info(gpointer value)
28 {
29 lrmd_rsc_info_t *rsc_info = value;
30
31 lrmd_free_rsc_info(rsc_info);
32 }
33
34 static void
35 free_deletion_op(gpointer value)
36 {
37 struct pending_deletion_op_s *op = value;
38
39 free(op->rsc);
40 delete_ha_msg_input(op->input);
41 free(op);
42 }
43
44 static void
45 free_recurring_op(gpointer value)
46 {
47 active_op_t *op = value;
48
49 free(op->user_data);
50 free(op->rsc_id);
51 free(op->op_type);
52 free(op->op_key);
53 if (op->params) {
54 g_hash_table_destroy(op->params);
55 }
56 free(op);
57 }
58
59 static gboolean
60 fail_pending_op(gpointer key, gpointer value, gpointer user_data)
61 {
62 lrmd_event_data_t event = { 0, };
63 lrm_state_t *lrm_state = user_data;
64 active_op_t *op = value;
65
66 crm_trace("Pre-emptively failing " PCMK__OP_FMT " on %s (call=%s, %s)",
67 op->rsc_id, op->op_type, op->interval_ms,
68 lrm_state->node_name, (char*)key, op->user_data);
69
70 event.type = lrmd_event_exec_complete;
71 event.rsc_id = op->rsc_id;
72 event.op_type = op->op_type;
73 event.user_data = op->user_data;
74 event.timeout = 0;
75 event.interval_ms = op->interval_ms;
76 event.rc = PCMK_OCF_UNKNOWN_ERROR;
77 event.op_status = PCMK_LRM_OP_NOT_CONNECTED;
78 event.t_run = (unsigned int) op->start_time;
79 event.t_rcchange = (unsigned int) op->start_time;
80
81 event.call_id = op->call_id;
82 event.remote_nodename = lrm_state->node_name;
83 event.params = op->params;
84
85 process_lrm_event(lrm_state, &event, op, NULL);
86 return TRUE;
87 }
88
89 gboolean
90 lrm_state_is_local(lrm_state_t *lrm_state)
91 {
92 if (lrm_state == NULL || fsa_our_uname == NULL) {
93 return FALSE;
94 }
95
96 if (strcmp(lrm_state->node_name, fsa_our_uname) != 0) {
97 return FALSE;
98 }
99
100 return TRUE;
101
102 }
103
104 lrm_state_t *
105 lrm_state_create(const char *node_name)
106 {
107 lrm_state_t *state = NULL;
108
109 if (!node_name) {
110 crm_err("No node name given for lrm state object");
111 return NULL;
112 }
113
114 state = calloc(1, sizeof(lrm_state_t));
115 if (!state) {
116 return NULL;
117 }
118
119 state->node_name = strdup(node_name);
120
121 state->rsc_info_cache = g_hash_table_new_full(crm_str_hash,
122 g_str_equal, NULL, free_rsc_info);
123
124 state->deletion_ops = g_hash_table_new_full(crm_str_hash, g_str_equal, free,
125 free_deletion_op);
126
127 state->pending_ops = g_hash_table_new_full(crm_str_hash, g_str_equal, free,
128 free_recurring_op);
129
130 state->resource_history = g_hash_table_new_full(crm_str_hash,
131 g_str_equal, NULL, history_free);
132
133 state->metadata_cache = metadata_cache_new();
134
135 g_hash_table_insert(lrm_state_table, (char *)state->node_name, state);
136 return state;
137
138 }
139
140 void
141 lrm_state_destroy(const char *node_name)
142 {
143 g_hash_table_remove(lrm_state_table, node_name);
144 }
145
146 static gboolean
147 remote_proxy_remove_by_node(gpointer key, gpointer value, gpointer user_data)
148 {
149 remote_proxy_t *proxy = value;
150 const char *node_name = user_data;
151
152 if (pcmk__str_eq(node_name, proxy->node_name, pcmk__str_casei)) {
153 return TRUE;
154 }
155
156 return FALSE;
157 }
158
159 static void
160 internal_lrm_state_destroy(gpointer data)
161 {
162 lrm_state_t *lrm_state = data;
163
164 if (!lrm_state) {
165 return;
166 }
167
168 crm_trace("Destroying proxy table %s with %d members", lrm_state->node_name, g_hash_table_size(proxy_table));
169 g_hash_table_foreach_remove(proxy_table, remote_proxy_remove_by_node, (char *) lrm_state->node_name);
170 remote_ra_cleanup(lrm_state);
171 lrmd_api_delete(lrm_state->conn);
172
173 if (lrm_state->rsc_info_cache) {
174 crm_trace("Destroying rsc info cache with %d members", g_hash_table_size(lrm_state->rsc_info_cache));
175 g_hash_table_destroy(lrm_state->rsc_info_cache);
176 }
177 if (lrm_state->resource_history) {
178 crm_trace("Destroying history op cache with %d members", g_hash_table_size(lrm_state->resource_history));
179 g_hash_table_destroy(lrm_state->resource_history);
180 }
181 if (lrm_state->deletion_ops) {
182 crm_trace("Destroying deletion op cache with %d members", g_hash_table_size(lrm_state->deletion_ops));
183 g_hash_table_destroy(lrm_state->deletion_ops);
184 }
185 if (lrm_state->pending_ops) {
186 crm_trace("Destroying pending op cache with %d members", g_hash_table_size(lrm_state->pending_ops));
187 g_hash_table_destroy(lrm_state->pending_ops);
188 }
189 metadata_cache_free(lrm_state->metadata_cache);
190
191 free((char *)lrm_state->node_name);
192 free(lrm_state);
193 }
194
195 void
196 lrm_state_reset_tables(lrm_state_t * lrm_state, gboolean reset_metadata)
197 {
198 if (lrm_state->resource_history) {
199 crm_trace("Re-setting history op cache with %d members",
200 g_hash_table_size(lrm_state->resource_history));
201 g_hash_table_remove_all(lrm_state->resource_history);
202 }
203 if (lrm_state->deletion_ops) {
204 crm_trace("Re-setting deletion op cache with %d members",
205 g_hash_table_size(lrm_state->deletion_ops));
206 g_hash_table_remove_all(lrm_state->deletion_ops);
207 }
208 if (lrm_state->pending_ops) {
209 crm_trace("Re-setting pending op cache with %d members",
210 g_hash_table_size(lrm_state->pending_ops));
211 g_hash_table_remove_all(lrm_state->pending_ops);
212 }
213 if (lrm_state->rsc_info_cache) {
214 crm_trace("Re-setting rsc info cache with %d members",
215 g_hash_table_size(lrm_state->rsc_info_cache));
216 g_hash_table_remove_all(lrm_state->rsc_info_cache);
217 }
218 if (reset_metadata) {
219 metadata_cache_reset(lrm_state->metadata_cache);
220 }
221 }
222
223 gboolean
224 lrm_state_init_local(void)
225 {
226 if (lrm_state_table) {
227 return TRUE;
228 }
229
230 lrm_state_table =
231 g_hash_table_new_full(crm_strcase_hash, crm_strcase_equal, NULL, internal_lrm_state_destroy);
232 if (!lrm_state_table) {
233 return FALSE;
234 }
235
236 proxy_table =
237 g_hash_table_new_full(crm_strcase_hash, crm_strcase_equal, NULL, remote_proxy_free);
238 if (!proxy_table) {
239 g_hash_table_destroy(lrm_state_table);
240 lrm_state_table = NULL;
241 return FALSE;
242 }
243
244 return TRUE;
245 }
246
247 void
248 lrm_state_destroy_all(void)
249 {
250 if (lrm_state_table) {
251 crm_trace("Destroying state table with %d members", g_hash_table_size(lrm_state_table));
252 g_hash_table_destroy(lrm_state_table); lrm_state_table = NULL;
253 }
254 if(proxy_table) {
255 crm_trace("Destroying proxy table with %d members", g_hash_table_size(proxy_table));
256 g_hash_table_destroy(proxy_table); proxy_table = NULL;
257 }
258 }
259
260 lrm_state_t *
261 lrm_state_find(const char *node_name)
262 {
263 if (!node_name) {
264 return NULL;
265 }
266 return g_hash_table_lookup(lrm_state_table, node_name);
267 }
268
269 lrm_state_t *
270 lrm_state_find_or_create(const char *node_name)
271 {
272 lrm_state_t *lrm_state;
273
274 lrm_state = g_hash_table_lookup(lrm_state_table, node_name);
275 if (!lrm_state) {
276 lrm_state = lrm_state_create(node_name);
277 }
278
279 return lrm_state;
280 }
281
282 GList *
283 lrm_state_get_list(void)
284 {
285 return g_hash_table_get_values(lrm_state_table);
286 }
287
288 static remote_proxy_t *
289 find_connected_proxy_by_node(const char * node_name)
290 {
291 GHashTableIter gIter;
292 remote_proxy_t *proxy = NULL;
293
294 CRM_CHECK(proxy_table != NULL, return NULL);
295
296 g_hash_table_iter_init(&gIter, proxy_table);
297
298 while (g_hash_table_iter_next(&gIter, NULL, (gpointer *) &proxy)) {
299 if (proxy->source
300 && pcmk__str_eq(node_name, proxy->node_name, pcmk__str_casei)) {
301 return proxy;
302 }
303 }
304
305 return NULL;
306 }
307
308 static void
309 remote_proxy_disconnect_by_node(const char * node_name)
310 {
311 remote_proxy_t *proxy = NULL;
312
313 CRM_CHECK(proxy_table != NULL, return);
314
315 while ((proxy = find_connected_proxy_by_node(node_name)) != NULL) {
316
317
318
319 if (proxy->source) {
320 mainloop_del_ipc_client(proxy->source);
321 }
322 }
323
324 return;
325 }
326
327 void
328 lrm_state_disconnect_only(lrm_state_t * lrm_state)
329 {
330 int removed = 0;
331
332 if (!lrm_state->conn) {
333 return;
334 }
335 crm_trace("Disconnecting %s", lrm_state->node_name);
336
337 remote_proxy_disconnect_by_node(lrm_state->node_name);
338
339 ((lrmd_t *) lrm_state->conn)->cmds->disconnect(lrm_state->conn);
340
341 if (!pcmk_is_set(fsa_input_register, R_SHUTDOWN)) {
342 removed = g_hash_table_foreach_remove(lrm_state->pending_ops, fail_pending_op, lrm_state);
343 crm_trace("Synthesized %d operation failures for %s", removed, lrm_state->node_name);
344 }
345 }
346
347 void
348 lrm_state_disconnect(lrm_state_t * lrm_state)
349 {
350 if (!lrm_state->conn) {
351 return;
352 }
353
354 lrm_state_disconnect_only(lrm_state);
355
356 lrmd_api_delete(lrm_state->conn);
357 lrm_state->conn = NULL;
358 }
359
360 int
361 lrm_state_is_connected(lrm_state_t * lrm_state)
362 {
363 if (!lrm_state->conn) {
364 return FALSE;
365 }
366 return ((lrmd_t *) lrm_state->conn)->cmds->is_connected(lrm_state->conn);
367 }
368
369 int
370 lrm_state_poke_connection(lrm_state_t * lrm_state)
371 {
372
373 if (!lrm_state->conn) {
374 return -1;
375 }
376 return ((lrmd_t *) lrm_state->conn)->cmds->poke_connection(lrm_state->conn);
377 }
378
379 int
380 lrm_state_ipc_connect(lrm_state_t * lrm_state)
381 {
382 int ret;
383
384 if (!lrm_state->conn) {
385 lrm_state->conn = lrmd_api_new();
386 ((lrmd_t *) lrm_state->conn)->cmds->set_callback(lrm_state->conn, lrm_op_callback);
387 }
388
389 ret = ((lrmd_t *) lrm_state->conn)->cmds->connect(lrm_state->conn, CRM_SYSTEM_CRMD, NULL);
390
391 if (ret != pcmk_ok) {
392 lrm_state->num_lrm_register_fails++;
393 } else {
394 lrm_state->num_lrm_register_fails = 0;
395 }
396
397 return ret;
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 = crm_str_table_new();
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 remote_proxy_check(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 time_t now = time(NULL);
501
502 crm_notice("%s requested shutdown of its remote connection",
503 lrm_state->node_name);
504
505 if (!remote_ra_is_in_maintenance(lrm_state)) {
506 now_s = crm_itoa(now);
507 update_attrd(lrm_state->node_name, XML_CIB_ATTR_SHUTDOWN, now_s, NULL, TRUE);
508 free(now_s);
509
510 remote_proxy_ack_shutdown(lrmd);
511
512 crm_warn("Reconnection attempts to %s may result in failures that must be cleared",
513 lrm_state->node_name);
514 } else {
515 remote_proxy_nack_shutdown(lrmd);
516
517 crm_notice("Remote resource for %s is not managed so no ordered shutdown happening",
518 lrm_state->node_name);
519 }
520 return;
521
522 } else if (pcmk__str_eq(op, LRMD_IPC_OP_REQUEST, pcmk__str_casei) && proxy && proxy->is_local) {
523
524
525
526 int flags = 0;
527 xmlNode *request = get_message_xml(msg, F_LRMD_IPC_MSG);
528
529 CRM_CHECK(request != NULL, return);
530 #if ENABLE_ACL
531 CRM_CHECK(lrm_state->node_name, return);
532 crm_xml_add(request, XML_ACL_TAG_ROLE, "pacemaker-remote");
533 pcmk__update_acl_user(request, F_LRMD_IPC_USER, lrm_state->node_name);
534 #endif
535
536
537
538
539
540
541 if (pcmk__str_eq(crm_element_value(request, F_CRM_TASK), CRM_OP_NODE_INFO, pcmk__str_casei)) {
542 int node_id = 0;
543
544 crm_element_value_int(request, XML_ATTR_ID, &node_id);
545 if ((node_id <= 0)
546 && (crm_element_value(request, XML_ATTR_UNAME) == NULL)) {
547 crm_xml_add(request, XML_ATTR_UNAME, lrm_state->node_name);
548 }
549 }
550
551 crmd_proxy_dispatch(session, request);
552
553 crm_element_value_int(msg, F_LRMD_IPC_MSG_FLAGS, &flags);
554 if (flags & crm_ipc_client_response) {
555 int msg_id = 0;
556 xmlNode *op_reply = create_xml_node(NULL, "ack");
557
558 crm_xml_add(op_reply, "function", __func__);
559 crm_xml_add_int(op_reply, "line", __LINE__);
560
561 crm_element_value_int(msg, F_LRMD_IPC_MSG_ID, &msg_id);
562 remote_proxy_relay_response(proxy, op_reply, msg_id);
563
564 free_xml(op_reply);
565 }
566
567 } else {
568 remote_proxy_cb(lrmd, lrm_state->node_name, msg);
569 }
570 }
571
572
573 int
574 lrm_state_remote_connect_async(lrm_state_t * lrm_state, const char *server, int port,
575 int timeout_ms)
576 {
577 int ret;
578
579 if (!lrm_state->conn) {
580 lrm_state->conn = lrmd_remote_api_new(lrm_state->node_name, server, port);
581 if (!lrm_state->conn) {
582 return -1;
583 }
584 ((lrmd_t *) lrm_state->conn)->cmds->set_callback(lrm_state->conn, remote_lrm_op_callback);
585 lrmd_internal_set_proxy_callback(lrm_state->conn, lrm_state, crmd_remote_proxy_cb);
586 }
587
588 crm_trace("initiating remote connection to %s at %d with timeout %d", server, port, timeout_ms);
589 ret =
590 ((lrmd_t *) lrm_state->conn)->cmds->connect_async(lrm_state->conn, lrm_state->node_name,
591 timeout_ms);
592
593 if (ret != pcmk_ok) {
594 lrm_state->num_lrm_register_fails++;
595 } else {
596 lrm_state->num_lrm_register_fails = 0;
597 }
598
599 return ret;
600 }
601
602 int
603 lrm_state_get_metadata(lrm_state_t * lrm_state,
604 const char *class,
605 const char *provider,
606 const char *agent, char **output, enum lrmd_call_options options)
607 {
608 lrmd_key_value_t *params = NULL;
609
610 if (!lrm_state->conn) {
611 return -ENOTCONN;
612 }
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628 params = lrmd_key_value_add(params, CRM_META "_" XML_LRM_ATTR_TARGET,
629 lrm_state->node_name);
630
631 return ((lrmd_t *) lrm_state->conn)->cmds->get_metadata_params(lrm_state->conn,
632 class, provider, agent, output, options, params);
633 }
634
635 int
636 lrm_state_cancel(lrm_state_t *lrm_state, const char *rsc_id, const char *action,
637 guint interval_ms)
638 {
639 if (!lrm_state->conn) {
640 return -ENOTCONN;
641 }
642
643
644
645 if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
646 return remote_ra_cancel(lrm_state, rsc_id, action, interval_ms);
647 }
648 return ((lrmd_t *) lrm_state->conn)->cmds->cancel(lrm_state->conn, rsc_id,
649 action, interval_ms);
650 }
651
652 lrmd_rsc_info_t *
653 lrm_state_get_rsc_info(lrm_state_t * lrm_state, const char *rsc_id, enum lrmd_call_options options)
654 {
655 lrmd_rsc_info_t *rsc = NULL;
656
657 if (!lrm_state->conn) {
658 return NULL;
659 }
660 if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
661 return remote_ra_get_rsc_info(lrm_state, rsc_id);
662 }
663
664 rsc = g_hash_table_lookup(lrm_state->rsc_info_cache, rsc_id);
665 if (rsc == NULL) {
666
667 rsc = ((lrmd_t *) lrm_state->conn)->cmds->get_rsc_info(lrm_state->conn, rsc_id, options);
668 if (rsc == NULL) {
669 return NULL;
670 }
671
672 g_hash_table_insert(lrm_state->rsc_info_cache, rsc->id, rsc);
673 }
674
675 return lrmd_copy_rsc_info(rsc);
676
677 }
678
679 int
680 lrm_state_exec(lrm_state_t *lrm_state, const char *rsc_id, const char *action,
681 const char *userdata, guint interval_ms,
682 int timeout,
683 int start_delay,
684 lrmd_key_value_t * params)
685 {
686
687 if (!lrm_state->conn) {
688 lrmd_key_value_freeall(params);
689 return -ENOTCONN;
690 }
691
692 if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
693 return remote_ra_exec(lrm_state, rsc_id, action, userdata, interval_ms,
694 timeout, start_delay, params);
695 }
696
697 return ((lrmd_t *) lrm_state->conn)->cmds->exec(lrm_state->conn,
698 rsc_id,
699 action,
700 userdata,
701 interval_ms,
702 timeout,
703 start_delay,
704 lrmd_opt_notify_changes_only, params);
705 }
706
707 int
708 lrm_state_register_rsc(lrm_state_t * lrm_state,
709 const char *rsc_id,
710 const char *class,
711 const char *provider, const char *agent, enum lrmd_call_options options)
712 {
713 lrmd_t *conn = (lrmd_t *) lrm_state->conn;
714
715 if (conn == NULL) {
716 return -ENOTCONN;
717 }
718
719 if (is_remote_lrmd_ra(agent, provider, NULL)) {
720 return lrm_state_find_or_create(rsc_id)? pcmk_ok : -EINVAL;
721 }
722
723
724
725
726 return conn->cmds->register_rsc(lrm_state->conn, rsc_id, class, provider,
727 agent, options);
728 }
729
730 int
731 lrm_state_unregister_rsc(lrm_state_t * lrm_state,
732 const char *rsc_id, enum lrmd_call_options options)
733 {
734 if (!lrm_state->conn) {
735 return -ENOTCONN;
736 }
737
738 if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
739 lrm_state_destroy(rsc_id);
740 return pcmk_ok;
741 }
742
743 g_hash_table_remove(lrm_state->rsc_info_cache, rsc_id);
744
745
746
747
748
749
750 return ((lrmd_t *) lrm_state->conn)->cmds->unregister_rsc(lrm_state->conn, rsc_id, options);
751 }
752
753
754
755
756
757 static GListPtr crmd_alert_list = NULL;
758
759 void
760 crmd_unpack_alerts(xmlNode *alerts)
761 {
762 pe_free_alert_list(crmd_alert_list);
763 crmd_alert_list = pe_unpack_alerts(alerts);
764 }
765
766 void
767 crmd_alert_node_event(crm_node_t *node)
768 {
769 lrm_state_t *lrm_state;
770
771 if (crmd_alert_list == NULL) {
772 return;
773 }
774
775 lrm_state = lrm_state_find(fsa_our_uname);
776 if (lrm_state == NULL) {
777 return;
778 }
779
780 lrmd_send_node_alert((lrmd_t *) lrm_state->conn, crmd_alert_list,
781 node->uname, node->id, node->state);
782 }
783
784 void
785 crmd_alert_fencing_op(stonith_event_t * e)
786 {
787 char *desc;
788 lrm_state_t *lrm_state;
789
790 if (crmd_alert_list == NULL) {
791 return;
792 }
793
794 lrm_state = lrm_state_find(fsa_our_uname);
795 if (lrm_state == NULL) {
796 return;
797 }
798
799 desc = crm_strdup_printf("Operation %s of %s by %s for %s@%s: %s (ref=%s)",
800 e->action, e->target,
801 (e->executioner? e->executioner : "<no-one>"),
802 e->client_origin, e->origin,
803 pcmk_strerror(e->result), e->id);
804
805 lrmd_send_fencing_alert((lrmd_t *) lrm_state->conn, crmd_alert_list,
806 e->target, e->operation, desc, e->result);
807 free(desc);
808 }
809
810 void
811 crmd_alert_resource_op(const char *node, lrmd_event_data_t * op)
812 {
813 lrm_state_t *lrm_state;
814
815 if (crmd_alert_list == NULL) {
816 return;
817 }
818
819 lrm_state = lrm_state_find(fsa_our_uname);
820 if (lrm_state == NULL) {
821 return;
822 }
823
824 lrmd_send_resource_alert((lrmd_t *) lrm_state->conn, crmd_alert_list, node,
825 op);
826 }