root/daemons/controld/controld_execd_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 2012-2020 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /* mainloop_del_ipc_client() eventually calls remote_proxy_disconnected()
 317          * , which removes the entry from proxy_table.
 318          * Do not do this in a g_hash_table_iter_next() loop. */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /* Now send it to the remote peer */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                 /* Look up stonith-watchdog-timeout and send to the remote peer for validation */
 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         /* This is for the controller, which we are, so don't try
 524          * to send to ourselves over IPC -- do it directly.
 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         /* Pacemaker Remote nodes don't know their own names (as known to the
 537          * cluster). When getting a node info request with no name or ID, add
 538          * the name, so we don't return info for ourselves instead of the
 539          * Pacemaker Remote node.
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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     /* Add the node name to the environment, as is done with normal resource
 615      * action calls. Meta-data calls shouldn't need it, but some agents are
 616      * written with an ocf_local_nodename call at the beginning regardless of
 617      * action. Without the environment variable, the agent would try to contact
 618      * the controller to get the node name -- but the controller would be
 619      * blocking on the synchronous meta-data call.
 620      *
 621      * At this point, we have to assume that agents are unlikely to make other
 622      * calls that require the controller, such as crm_node --quorum or
 623      * --cluster-id.
 624      *
 625      * @TODO Make meta-data calls asynchronous. (This will be part of a larger
 626      * project to make meta-data calls via the executor rather than directly.)
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 637                  guint interval_ms)
 638 {
 639     if (!lrm_state->conn) {
 640         return -ENOTCONN;
 641     }
 642 
 643     /* Figure out a way to make this async?
 644      * NOTICE: Currently it's synced and directly acknowledged in do_lrm_invoke(). */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /* only contact the lrmd if we don't already have a cached rsc info */
 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         /* cache the result */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 681                const char *userdata, guint interval_ms,
 682                int timeout,     /* ms */
 683                int start_delay, /* ms */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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     /* @TODO Implement an asynchronous version of this (currently a blocking
 724      * call to the lrmd).
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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     /* @TODO Optimize this ... this function is a blocking round trip from
 746      * client to daemon. The controld_execd_state.c code path that uses this
 747      * function should always treat it as an async operation. The executor API
 748      * should make an async version available.
 749      */
 750     return ((lrmd_t *) lrm_state->conn)->cmds->unregister_rsc(lrm_state->conn, rsc_id, options);
 751 }
 752 
 753 /*
 754  * Functions for sending alerts via local executor connection
 755  */
 756 
 757 static GListPtr crmd_alert_list = NULL;
 758 
 759 void
 760 crmd_unpack_alerts(xmlNode *alerts)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 }

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