root/crmd/lrm_state.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. free_rsc_info
  2. free_deletion_op
  3. free_recurring_op
  4. fail_pending_op
  5. lrm_state_is_local
  6. lrm_state_create
  7. lrm_state_destroy
  8. remote_proxy_remove_by_node
  9. internal_lrm_state_destroy
  10. lrm_state_reset_tables
  11. lrm_state_init_local
  12. lrm_state_destroy_all
  13. lrm_state_find
  14. lrm_state_find_or_create
  15. lrm_state_get_list
  16. find_connected_proxy_by_node
  17. remote_proxy_disconnect_by_node
  18. lrm_state_disconnect_only
  19. lrm_state_disconnect
  20. lrm_state_is_connected
  21. lrm_state_poke_connection
  22. lrm_state_ipc_connect
  23. crmd_remote_proxy_new
  24. crmd_is_proxy_session
  25. crmd_proxy_send
  26. crmd_proxy_dispatch
  27. remote_config_check
  28. crmd_remote_proxy_cb
  29. lrm_state_remote_connect_async
  30. lrm_state_get_metadata
  31. lrm_state_cancel
  32. lrm_state_get_rsc_info
  33. lrm_state_exec
  34. lrm_state_register_rsc
  35. lrm_state_unregister_rsc
  36. crmd_unpack_alerts
  37. crmd_alert_node_event
  38. crmd_alert_fencing_op
  39. crmd_alert_resource_op

   1 /* 
   2  * Copyright (C) 2012 David Vossel <davidvossel@gmail.com>
   3  * 
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2 of the License, or (at your option) any later version.
   8  * 
   9  * This software is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * General Public License for more details.
  13  * 
  14  * You should have received a copy of the GNU General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17  */
  18 
  19 #include <crm_internal.h>
  20 #include <crm/crm.h>
  21 #include <crm/msg_xml.h>
  22 #include <crm/common/iso8601.h>
  23 
  24 #include <crmd.h>
  25 #include <crmd_fsa.h>
  26 #include <crmd_messages.h>
  27 #include <crmd_callbacks.h>
  28 #include <crmd_lrm.h>
  29 #include <crmd_alerts.h>
  30 #include <crm/pengine/rules.h>
  31 #include <crm/pengine/rules_internal.h>
  32 #include <crm/transition.h>
  33 #include <crm/lrmd_alerts_internal.h>
  34 
  35 GHashTable *lrm_state_table = NULL;
  36 extern GHashTable *proxy_table;
  37 int lrmd_internal_proxy_send(lrmd_t * lrmd, xmlNode *msg);
  38 void lrmd_internal_set_proxy_callback(lrmd_t * lrmd, void *userdata, void (*callback)(lrmd_t *lrmd, void *userdata, xmlNode *msg));
  39 
  40 static void
  41 free_rsc_info(gpointer value)
     /* [previous][next][first][last][top][bottom][index][help] */
  42 {
  43     lrmd_rsc_info_t *rsc_info = value;
  44 
  45     lrmd_free_rsc_info(rsc_info);
  46 }
  47 
  48 static void
  49 free_deletion_op(gpointer value)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51     struct pending_deletion_op_s *op = value;
  52 
  53     free(op->rsc);
  54     delete_ha_msg_input(op->input);
  55     free(op);
  56 }
  57 
  58 static void
  59 free_recurring_op(gpointer value)
     /* [previous][next][first][last][top][bottom][index][help] */
  60 {
  61     struct recurring_op_s *op = (struct recurring_op_s *)value;
  62 
  63     free(op->user_data);
  64     free(op->rsc_id);
  65     free(op->op_type);
  66     free(op->op_key);
  67     if (op->params) {
  68         g_hash_table_destroy(op->params);
  69     }
  70     free(op);
  71 }
  72 
  73 static gboolean
  74 fail_pending_op(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  75 {
  76     lrmd_event_data_t event = { 0, };
  77     lrm_state_t *lrm_state = user_data;
  78     struct recurring_op_s *op = (struct recurring_op_s *)value;
  79 
  80     crm_trace("Pre-emptively failing %s_%s_%d on %s (call=%s, %s)",
  81               op->rsc_id, op->op_type, op->interval,
  82               lrm_state->node_name, (char*)key, op->user_data);
  83 
  84     event.type = lrmd_event_exec_complete;
  85     event.rsc_id = op->rsc_id;
  86     event.op_type = op->op_type;
  87     event.user_data = op->user_data;
  88     event.timeout = 0;
  89     event.interval = op->interval;
  90     event.rc = PCMK_OCF_CONNECTION_DIED;
  91     event.op_status = PCMK_LRM_OP_ERROR;
  92     event.t_run = op->start_time;
  93     event.t_rcchange = op->start_time;
  94 
  95     event.call_id = op->call_id;
  96     event.remote_nodename = lrm_state->node_name;
  97     event.params = op->params;
  98 
  99     process_lrm_event(lrm_state, &event, op);
 100     return TRUE;
 101 }
 102 
 103 gboolean
 104 lrm_state_is_local(lrm_state_t *lrm_state)
     /* [previous][next][first][last][top][bottom][index][help] */
 105 {
 106     if (lrm_state == NULL || fsa_our_uname == NULL) {
 107         return FALSE;
 108     }
 109 
 110     if (strcmp(lrm_state->node_name, fsa_our_uname) != 0) {
 111         return FALSE;
 112     }
 113 
 114     return TRUE;
 115 
 116 }
 117 
 118 lrm_state_t *
 119 lrm_state_create(const char *node_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121     lrm_state_t *state = NULL;
 122 
 123     if (!node_name) {
 124         crm_err("No node name given for lrm state object");
 125         return NULL;
 126     }
 127 
 128     state = calloc(1, sizeof(lrm_state_t));
 129     if (!state) {
 130         return NULL;
 131     }
 132 
 133     state->node_name = strdup(node_name);
 134 
 135     state->rsc_info_cache = g_hash_table_new_full(crm_str_hash,
 136                                                 g_str_equal, NULL, free_rsc_info);
 137 
 138     state->deletion_ops = g_hash_table_new_full(crm_str_hash,
 139                                                 g_str_equal, g_hash_destroy_str, free_deletion_op);
 140 
 141     state->pending_ops = g_hash_table_new_full(crm_str_hash,
 142                                                g_str_equal, g_hash_destroy_str, free_recurring_op);
 143 
 144     state->resource_history = g_hash_table_new_full(crm_str_hash,
 145                                                     g_str_equal, NULL, history_free);
 146 
 147     state->metadata_cache = metadata_cache_new();
 148 
 149     g_hash_table_insert(lrm_state_table, (char *)state->node_name, state);
 150     return state;
 151 
 152 }
 153 
 154 void
 155 lrm_state_destroy(const char *node_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157     g_hash_table_remove(lrm_state_table, node_name);
 158 }
 159 
 160 static gboolean
 161 remote_proxy_remove_by_node(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163     remote_proxy_t *proxy = value;
 164     const char *node_name = user_data;
 165 
 166     if (safe_str_eq(node_name, proxy->node_name)) {
 167         return TRUE;
 168     }
 169 
 170     return FALSE;
 171 }
 172 
 173 static void
 174 internal_lrm_state_destroy(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176     lrm_state_t *lrm_state = data;
 177 
 178     if (!lrm_state) {
 179         return;
 180     }
 181 
 182     crm_trace("Destroying proxy table %s with %d members", lrm_state->node_name, g_hash_table_size(proxy_table));
 183     g_hash_table_foreach_remove(proxy_table, remote_proxy_remove_by_node, (char *) lrm_state->node_name);
 184     remote_ra_cleanup(lrm_state);
 185     lrmd_api_delete(lrm_state->conn);
 186 
 187     if (lrm_state->rsc_info_cache) {
 188         crm_trace("Destroying rsc info cache with %d members", g_hash_table_size(lrm_state->rsc_info_cache));
 189         g_hash_table_destroy(lrm_state->rsc_info_cache);
 190     }
 191     if (lrm_state->resource_history) {
 192         crm_trace("Destroying history op cache with %d members", g_hash_table_size(lrm_state->resource_history));
 193         g_hash_table_destroy(lrm_state->resource_history);
 194     }
 195     if (lrm_state->deletion_ops) {
 196         crm_trace("Destroying deletion op cache with %d members", g_hash_table_size(lrm_state->deletion_ops));
 197         g_hash_table_destroy(lrm_state->deletion_ops);
 198     }
 199     if (lrm_state->pending_ops) {
 200         crm_trace("Destroying pending op cache with %d members", g_hash_table_size(lrm_state->pending_ops));
 201         g_hash_table_destroy(lrm_state->pending_ops);
 202     }
 203     metadata_cache_free(lrm_state->metadata_cache);
 204 
 205     free((char *)lrm_state->node_name);
 206     free(lrm_state);
 207 }
 208 
 209 void
 210 lrm_state_reset_tables(lrm_state_t * lrm_state, gboolean reset_metadata)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212     if (lrm_state->resource_history) {
 213         crm_trace("Re-setting history op cache with %d members",
 214                   g_hash_table_size(lrm_state->resource_history));
 215         g_hash_table_remove_all(lrm_state->resource_history);
 216     }
 217     if (lrm_state->deletion_ops) {
 218         crm_trace("Re-setting deletion op cache with %d members",
 219                   g_hash_table_size(lrm_state->deletion_ops));
 220         g_hash_table_remove_all(lrm_state->deletion_ops);
 221     }
 222     if (lrm_state->pending_ops) {
 223         crm_trace("Re-setting pending op cache with %d members",
 224                   g_hash_table_size(lrm_state->pending_ops));
 225         g_hash_table_remove_all(lrm_state->pending_ops);
 226     }
 227     if (lrm_state->rsc_info_cache) {
 228         crm_trace("Re-setting rsc info cache with %d members",
 229                   g_hash_table_size(lrm_state->rsc_info_cache));
 230         g_hash_table_remove_all(lrm_state->rsc_info_cache);
 231     }
 232     if (reset_metadata) {
 233         metadata_cache_reset(lrm_state->metadata_cache);
 234     }
 235 }
 236 
 237 gboolean
 238 lrm_state_init_local(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 239 {
 240     if (lrm_state_table) {
 241         return TRUE;
 242     }
 243 
 244     lrm_state_table =
 245         g_hash_table_new_full(crm_strcase_hash, crm_strcase_equal, NULL, internal_lrm_state_destroy);
 246     if (!lrm_state_table) {
 247         return FALSE;
 248     }
 249 
 250     proxy_table =
 251         g_hash_table_new_full(crm_strcase_hash, crm_strcase_equal, NULL, remote_proxy_free);
 252     if (!proxy_table) {
 253         g_hash_table_destroy(lrm_state_table);
 254         lrm_state_table = NULL;
 255         return FALSE;
 256     }
 257 
 258     return TRUE;
 259 }
 260 
 261 void
 262 lrm_state_destroy_all(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264     if (lrm_state_table) {
 265         crm_trace("Destroying state table with %d members", g_hash_table_size(lrm_state_table));
 266         g_hash_table_destroy(lrm_state_table); lrm_state_table = NULL;
 267     }
 268     if(proxy_table) {
 269         crm_trace("Destroying proxy table with %d members", g_hash_table_size(proxy_table));
 270         g_hash_table_destroy(proxy_table); proxy_table = NULL;
 271     }
 272 }
 273 
 274 lrm_state_t *
 275 lrm_state_find(const char *node_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 276 {
 277     if (!node_name) {
 278         return NULL;
 279     }
 280     return g_hash_table_lookup(lrm_state_table, node_name);
 281 }
 282 
 283 lrm_state_t *
 284 lrm_state_find_or_create(const char *node_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286     lrm_state_t *lrm_state;
 287 
 288     lrm_state = g_hash_table_lookup(lrm_state_table, node_name);
 289     if (!lrm_state) {
 290         lrm_state = lrm_state_create(node_name);
 291     }
 292 
 293     return lrm_state;
 294 }
 295 
 296 GList *
 297 lrm_state_get_list(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 298 {
 299     return g_hash_table_get_values(lrm_state_table);
 300 }
 301 
 302 static remote_proxy_t *
 303 find_connected_proxy_by_node(const char * node_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 304 {
 305     GHashTableIter gIter;
 306     remote_proxy_t *proxy = NULL;
 307 
 308     CRM_CHECK(proxy_table != NULL, return NULL);
 309 
 310     g_hash_table_iter_init(&gIter, proxy_table);
 311 
 312     while (g_hash_table_iter_next(&gIter, NULL, (gpointer *) &proxy)) {
 313         if (proxy->source
 314             && safe_str_eq(node_name, proxy->node_name)) {
 315             return proxy;
 316         }
 317     }
 318 
 319     return NULL;
 320 }
 321 
 322 static void
 323 remote_proxy_disconnect_by_node(const char * node_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 324 {
 325     remote_proxy_t *proxy = NULL;
 326 
 327     CRM_CHECK(proxy_table != NULL, return);
 328 
 329     while ((proxy = find_connected_proxy_by_node(node_name)) != NULL) {
 330         /* mainloop_del_ipc_client() eventually calls remote_proxy_disconnected()
 331          * , which removes the entry from proxy_table.
 332          * Do not do this in a g_hash_table_iter_next() loop. */
 333         if (proxy->source) {
 334             mainloop_del_ipc_client(proxy->source);
 335         }
 336     }
 337 
 338     return;
 339 }
 340 
 341 void
 342 lrm_state_disconnect_only(lrm_state_t * lrm_state)
     /* [previous][next][first][last][top][bottom][index][help] */
 343 {
 344     int removed = 0;
 345 
 346     if (!lrm_state->conn) {
 347         return;
 348     }
 349     crm_trace("Disconnecting %s", lrm_state->node_name);
 350 
 351     remote_proxy_disconnect_by_node(lrm_state->node_name);
 352 
 353     ((lrmd_t *) lrm_state->conn)->cmds->disconnect(lrm_state->conn);
 354 
 355     if (is_not_set(fsa_input_register, R_SHUTDOWN)) {
 356         removed = g_hash_table_foreach_remove(lrm_state->pending_ops, fail_pending_op, lrm_state);
 357         crm_trace("Synthesized %d operation failures for %s", removed, lrm_state->node_name);
 358     }
 359 }
 360 
 361 void
 362 lrm_state_disconnect(lrm_state_t * lrm_state)
     /* [previous][next][first][last][top][bottom][index][help] */
 363 {
 364     if (!lrm_state->conn) {
 365         return;
 366     }
 367 
 368     lrm_state_disconnect_only(lrm_state);
 369 
 370     lrmd_api_delete(lrm_state->conn);
 371     lrm_state->conn = NULL;
 372 }
 373 
 374 int
 375 lrm_state_is_connected(lrm_state_t * lrm_state)
     /* [previous][next][first][last][top][bottom][index][help] */
 376 {
 377     if (!lrm_state->conn) {
 378         return FALSE;
 379     }
 380     return ((lrmd_t *) lrm_state->conn)->cmds->is_connected(lrm_state->conn);
 381 }
 382 
 383 int
 384 lrm_state_poke_connection(lrm_state_t * lrm_state)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386 
 387     if (!lrm_state->conn) {
 388         return -1;
 389     }
 390     return ((lrmd_t *) lrm_state->conn)->cmds->poke_connection(lrm_state->conn);
 391 }
 392 
 393 int
 394 lrm_state_ipc_connect(lrm_state_t * lrm_state)
     /* [previous][next][first][last][top][bottom][index][help] */
 395 {
 396     int ret;
 397 
 398     if (!lrm_state->conn) {
 399         lrm_state->conn = lrmd_api_new();
 400         ((lrmd_t *) lrm_state->conn)->cmds->set_callback(lrm_state->conn, lrm_op_callback);
 401     }
 402 
 403     ret = ((lrmd_t *) lrm_state->conn)->cmds->connect(lrm_state->conn, CRM_SYSTEM_CRMD, NULL);
 404 
 405     if (ret != pcmk_ok) {
 406         lrm_state->num_lrm_register_fails++;
 407     } else {
 408         lrm_state->num_lrm_register_fails = 0;
 409     }
 410 
 411     return ret;
 412 }
 413 
 414 static remote_proxy_t *
 415 crmd_remote_proxy_new(lrmd_t *lrmd, const char *node_name, const char *session_id, const char *channel)
     /* [previous][next][first][last][top][bottom][index][help] */
 416 {
 417     static struct ipc_client_callbacks proxy_callbacks = {
 418         .dispatch = remote_proxy_dispatch,
 419         .destroy = remote_proxy_disconnected
 420     };
 421     remote_proxy_t *proxy = remote_proxy_new(lrmd, &proxy_callbacks, node_name,
 422                                              session_id, channel);
 423     return proxy;
 424 }
 425 
 426 gboolean
 427 crmd_is_proxy_session(const char *session)
     /* [previous][next][first][last][top][bottom][index][help] */
 428 {
 429     return g_hash_table_lookup(proxy_table, session) ? TRUE : FALSE;
 430 }
 431 
 432 void
 433 crmd_proxy_send(const char *session, xmlNode *msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 434 {
 435     remote_proxy_t *proxy = g_hash_table_lookup(proxy_table, session);
 436     lrm_state_t *lrm_state = NULL;
 437 
 438     if (!proxy) {
 439         return;
 440     }
 441     crm_log_xml_trace(msg, "to-proxy");
 442     lrm_state = lrm_state_find(proxy->node_name);
 443     if (lrm_state) {
 444         crm_trace("Sending event to %.8s on %s", proxy->session_id, proxy->node_name);
 445         remote_proxy_relay_event(proxy, msg);
 446     }
 447 }
 448 
 449 static void
 450 crmd_proxy_dispatch(const char *session, xmlNode *msg)
     /* [previous][next][first][last][top][bottom][index][help] */
 451 {
 452 
 453     crm_log_xml_trace(msg, "CRMd-PROXY[inbound]");
 454 
 455     crm_xml_add(msg, F_CRM_SYS_FROM, session);
 456     if (crmd_authorize_message(msg, NULL, session)) {
 457         route_message(C_IPC_MESSAGE, msg);
 458     }
 459 
 460     trigger_fsa(fsa_source);
 461 }
 462 
 463 static void
 464 remote_config_check(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 = crm_str_table_new();
 477 
 478         crm_debug("Call %d : Parsing CIB options", call_id);
 479 
 480         unpack_instance_attributes(
 481             output, output, XML_CIB_TAG_PROPSET, NULL, config_hash, CIB_OPTIONS_FIRST, FALSE, now);
 482 
 483         /* Now send it to the remote peer */
 484         remote_proxy_check(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)
     /* [previous][next][first][last][top][bottom][index][help] */
 493 {
 494     lrm_state_t *lrm_state = userdata;
 495     const char *session = crm_element_value(msg, F_LRMD_IPC_SESSION);
 496     remote_proxy_t *proxy = g_hash_table_lookup(proxy_table, session);
 497 
 498     const char *op = crm_element_value(msg, F_LRMD_IPC_OP);
 499     if (safe_str_eq(op, LRMD_IPC_OP_NEW)) {
 500         const char *channel = crm_element_value(msg, F_LRMD_IPC_IPC_SERVER);
 501 
 502         proxy = crmd_remote_proxy_new(lrmd, lrm_state->node_name, session, channel);
 503         if (proxy != NULL) {
 504             /* Look up stonith-watchdog-timeout and send to the remote peer for validation */
 505             int rc = fsa_cib_conn->cmds->query(fsa_cib_conn, XML_CIB_TAG_CRMCONFIG, NULL, cib_scope_local);
 506             fsa_cib_conn->cmds->register_callback_full(fsa_cib_conn, rc, 10, FALSE, lrmd,
 507                                                        "remote_config_check", remote_config_check, NULL);
 508         }
 509 
 510     } else if (safe_str_eq(op, LRMD_IPC_OP_SHUTDOWN_REQ)) {
 511         char *now_s = NULL;
 512         time_t now = time(NULL);
 513 
 514         crm_notice("%s requested shutdown of its remote connection",
 515                    lrm_state->node_name);
 516 
 517         if (!remote_ra_is_in_maintenance(lrm_state)) {
 518             now_s = crm_itoa(now);
 519             update_attrd(lrm_state->node_name, XML_CIB_ATTR_SHUTDOWN, now_s, NULL, TRUE);
 520             free(now_s);
 521 
 522             remote_proxy_ack_shutdown(lrmd);
 523 
 524             crm_warn("Reconnection attempts to %s may result in failures that must be cleared",
 525                     lrm_state->node_name);
 526         } else {
 527             remote_proxy_nack_shutdown(lrmd);
 528 
 529             crm_notice("Remote resource for %s is not managed so no ordered shutdown happening",
 530                     lrm_state->node_name);
 531         }
 532         return;
 533 
 534     } else if (safe_str_eq(op, LRMD_IPC_OP_REQUEST) && proxy && proxy->is_local) {
 535         /* this is for the crmd, which we are, so don't try
 536          * and connect/send to ourselves over ipc. instead
 537          * do it directly.
 538          */
 539         int flags = 0;
 540         xmlNode *request = get_message_xml(msg, F_LRMD_IPC_MSG);
 541 
 542         CRM_CHECK(request != NULL, return);
 543 #if ENABLE_ACL
 544         CRM_CHECK(lrm_state->node_name, return);
 545         crm_xml_add(request, XML_ACL_TAG_ROLE, "pacemaker-remote");
 546         crm_acl_get_set_user(request, F_LRMD_IPC_USER, lrm_state->node_name);
 547 #endif
 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", __FUNCTION__);
 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 int
 571 lrm_state_remote_connect_async(lrm_state_t * lrm_state, const char *server, int port,
     /* [previous][next][first][last][top][bottom][index][help] */
 572                                int timeout_ms)
 573 {
 574     int ret;
 575 
 576     if (!lrm_state->conn) {
 577         lrm_state->conn = lrmd_remote_api_new(lrm_state->node_name, server, port);
 578         if (!lrm_state->conn) {
 579             return -1;
 580         }
 581         ((lrmd_t *) lrm_state->conn)->cmds->set_callback(lrm_state->conn, remote_lrm_op_callback);
 582         lrmd_internal_set_proxy_callback(lrm_state->conn, lrm_state, crmd_remote_proxy_cb);
 583     }
 584 
 585     crm_trace("initiating remote connection to %s at %d with timeout %d", server, port, timeout_ms);
 586     ret =
 587         ((lrmd_t *) lrm_state->conn)->cmds->connect_async(lrm_state->conn, lrm_state->node_name,
 588                                                           timeout_ms);
 589 
 590     if (ret != pcmk_ok) {
 591         lrm_state->num_lrm_register_fails++;
 592     } else {
 593         lrm_state->num_lrm_register_fails = 0;
 594     }
 595 
 596     return ret;
 597 }
 598 
 599 int
 600 lrm_state_get_metadata(lrm_state_t * lrm_state,
     /* [previous][next][first][last][top][bottom][index][help] */
 601                        const char *class,
 602                        const char *provider,
 603                        const char *agent, char **output, enum lrmd_call_options options)
 604 {
 605     if (!lrm_state->conn) {
 606         return -ENOTCONN;
 607     }
 608     return ((lrmd_t *) lrm_state->conn)->cmds->get_metadata(lrm_state->conn, class, provider, agent,
 609                                                             output, options);
 610 }
 611 
 612 int
 613 lrm_state_cancel(lrm_state_t * lrm_state, const char *rsc_id, const char *action, int interval)
     /* [previous][next][first][last][top][bottom][index][help] */
 614 {
 615     if (!lrm_state->conn) {
 616         return -ENOTCONN;
 617     }
 618 
 619     /* Figure out a way to make this async?
 620      * NOTICE: Currently it's synced and directly acknowledged in do_lrm_invoke(). */
 621     if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
 622         return remote_ra_cancel(lrm_state, rsc_id, action, interval);
 623     }
 624     return ((lrmd_t *) lrm_state->conn)->cmds->cancel(lrm_state->conn, rsc_id, action, interval);
 625 }
 626 
 627 lrmd_rsc_info_t *
 628 lrm_state_get_rsc_info(lrm_state_t * lrm_state, const char *rsc_id, enum lrmd_call_options options)
     /* [previous][next][first][last][top][bottom][index][help] */
 629 {
 630     lrmd_rsc_info_t *rsc = NULL;
 631 
 632     if (!lrm_state->conn) {
 633         return NULL;
 634     }
 635     if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
 636         return remote_ra_get_rsc_info(lrm_state, rsc_id);
 637     }
 638 
 639     rsc = g_hash_table_lookup(lrm_state->rsc_info_cache, rsc_id);
 640     if (rsc == NULL) {
 641         /* only contact the lrmd if we don't already have a cached rsc info */
 642         rsc = ((lrmd_t *) lrm_state->conn)->cmds->get_rsc_info(lrm_state->conn, rsc_id, options);
 643         if (rsc == NULL) {
 644                     return NULL;
 645         }
 646         /* cache the result */
 647         g_hash_table_insert(lrm_state->rsc_info_cache, rsc->id, rsc);
 648     }
 649 
 650     return lrmd_copy_rsc_info(rsc);
 651 
 652 }
 653 
 654 int
 655 lrm_state_exec(lrm_state_t * lrm_state, const char *rsc_id, const char *action, const char *userdata, int interval,     /* ms */
     /* [previous][next][first][last][top][bottom][index][help] */
 656                int timeout,     /* ms */
 657                int start_delay, /* ms */
 658                lrmd_key_value_t * params)
 659 {
 660 
 661     if (!lrm_state->conn) {
 662         lrmd_key_value_freeall(params);
 663         return -ENOTCONN;
 664     }
 665 
 666     if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
 667         return remote_ra_exec(lrm_state,
 668                               rsc_id, action, userdata, interval, timeout, start_delay, params);
 669     }
 670 
 671     return ((lrmd_t *) lrm_state->conn)->cmds->exec(lrm_state->conn,
 672                                                     rsc_id,
 673                                                     action,
 674                                                     userdata,
 675                                                     interval,
 676                                                     timeout,
 677                                                     start_delay,
 678                                                     lrmd_opt_notify_changes_only, params);
 679 }
 680 
 681 int
 682 lrm_state_register_rsc(lrm_state_t * lrm_state,
     /* [previous][next][first][last][top][bottom][index][help] */
 683                        const char *rsc_id,
 684                        const char *class,
 685                        const char *provider, const char *agent, enum lrmd_call_options options)
 686 {
 687     if (!lrm_state->conn) {
 688         return -ENOTCONN;
 689     }
 690 
 691     /* optimize this... this function is a synced round trip from client to daemon.
 692      * The crmd/lrm.c code path should be re-factored to allow the register of resources
 693      * to be performed async. The lrmd client api needs to make an async version
 694      * of register available. */
 695     if (is_remote_lrmd_ra(agent, provider, NULL)) {
 696         return lrm_state_find_or_create(rsc_id) ? pcmk_ok : -1;
 697     }
 698 
 699     return ((lrmd_t *) lrm_state->conn)->cmds->register_rsc(lrm_state->conn, rsc_id, class,
 700                                                             provider, agent, options);
 701 }
 702 
 703 int
 704 lrm_state_unregister_rsc(lrm_state_t * lrm_state,
     /* [previous][next][first][last][top][bottom][index][help] */
 705                          const char *rsc_id, enum lrmd_call_options options)
 706 {
 707     if (!lrm_state->conn) {
 708         return -ENOTCONN;
 709     }
 710 
 711     /* optimize this... this function is a synced round trip from client to daemon.
 712      * The crmd/lrm.c code path that uses this function should always treat it as an
 713      * async operation. The lrmd client api needs to make an async version unreg available. */
 714     if (is_remote_lrmd_ra(NULL, NULL, rsc_id)) {
 715         lrm_state_destroy(rsc_id);
 716         return pcmk_ok;
 717     }
 718 
 719     g_hash_table_remove(lrm_state->rsc_info_cache, rsc_id);
 720 
 721     return ((lrmd_t *) lrm_state->conn)->cmds->unregister_rsc(lrm_state->conn, rsc_id, options);
 722 }
 723 
 724 /*
 725  * functions for sending alerts via local LRMD connection
 726  */
 727 
 728 static GListPtr crmd_alert_list = NULL;
 729 
 730 void
 731 crmd_unpack_alerts(xmlNode *alerts)
     /* [previous][next][first][last][top][bottom][index][help] */
 732 {
 733     pe_free_alert_list(crmd_alert_list);
 734     crmd_alert_list = pe_unpack_alerts(alerts);
 735 }
 736 
 737 void
 738 crmd_alert_node_event(crm_node_t *node)
     /* [previous][next][first][last][top][bottom][index][help] */
 739 {
 740     lrm_state_t *lrm_state;
 741 
 742     if (crmd_alert_list == NULL) {
 743         return;
 744     }
 745 
 746     lrm_state = lrm_state_find(fsa_our_uname);
 747     if (lrm_state == NULL) {
 748         return;
 749     }
 750 
 751     lrmd_send_node_alert((lrmd_t *) lrm_state->conn, crmd_alert_list,
 752                          node->uname, node->id, node->state);
 753 }
 754 
 755 void
 756 crmd_alert_fencing_op(stonith_event_t * e)
     /* [previous][next][first][last][top][bottom][index][help] */
 757 {
 758     char *desc;
 759     lrm_state_t *lrm_state;
 760 
 761     if (crmd_alert_list == NULL) {
 762         return;
 763     }
 764 
 765     lrm_state = lrm_state_find(fsa_our_uname);
 766     if (lrm_state == NULL) {
 767         return;
 768     }
 769 
 770     desc = crm_strdup_printf("Operation %s of %s by %s for %s@%s: %s (ref=%s)",
 771                              e->action, e->target,
 772                              (e->executioner? e->executioner : "<no-one>"),
 773                              e->client_origin, e->origin,
 774                              pcmk_strerror(e->result), e->id);
 775 
 776     lrmd_send_fencing_alert((lrmd_t *) lrm_state->conn, crmd_alert_list,
 777                             e->target, e->operation, desc, e->result);
 778     free(desc);
 779 }
 780 
 781 void
 782 crmd_alert_resource_op(const char *node, lrmd_event_data_t * op)
     /* [previous][next][first][last][top][bottom][index][help] */
 783 {
 784     lrm_state_t *lrm_state;
 785 
 786     if (crmd_alert_list == NULL) {
 787         return;
 788     }
 789 
 790     lrm_state = lrm_state_find(fsa_our_uname);
 791     if (lrm_state == NULL) {
 792         return;
 793     }
 794 
 795     lrmd_send_resource_alert((lrmd_t *) lrm_state->conn, crmd_alert_list, node,
 796                              op);
 797 }

/* [previous][next][first][last][top][bottom][index][help] */