Example #1
0
static void
handle_local_reply_and_notify(remote_fencing_op_t * op, xmlNode * data, int rc)
{
    xmlNode *notify_data = NULL;
    xmlNode *reply = NULL;

    if (op->notify_sent == TRUE) {
        /* nothing to do */
        return;
    }

    /* Do notification with a clean data object */
    notify_data = create_op_done_notify(op, rc);
    crm_xml_add_int(data, "state", op->state);
    crm_xml_add(data, F_STONITH_TARGET, op->target);
    crm_xml_add(data, F_STONITH_OPERATION, op->action);

    reply = stonith_construct_reply(op->request, NULL, data, rc);
    crm_xml_add(reply, F_STONITH_DELEGATE, op->delegate);

    /* Send fencing OP reply to local client that initiated fencing */
    do_local_reply(reply, op->client_id, op->call_options & st_opt_sync_call, FALSE);

    /* bcast to all local clients that the fencing operation happend */
    do_stonith_notify(0, T_STONITH_NOTIFY_FENCE, rc, notify_data);

    /* mark this op as having notify's already sent */
    op->notify_sent = TRUE;
    free_xml(reply);
    free_xml(notify_data);
}
Example #2
0
/*!
 * \internal
 * \brief Send out a cleanup broadcast or do a local history-cleanup
 *
 * \param[in] target    Cleanup can be limited to certain fence-targets
 * \param[in] broadcast Send out a cleanup broadcast
 */
static void
stonith_fence_history_cleanup(const char *target,
                              gboolean broadcast)
{
    if (broadcast) {
        stonith_send_broadcast_history(NULL,
                                       st_opt_cleanup | st_opt_discard_reply,
                                       target);
        /* we'll do the local clean when we receive back our own broadcast */
    } else if (stonith_remote_op_list) {
        g_hash_table_foreach_remove(stonith_remote_op_list,
                             stonith_remove_history_entry,
                             (gpointer) target);
        do_stonith_notify(0, T_STONITH_NOTIFY_HISTORY, 0, NULL);
    }
}
Example #3
0
/*!
 * \internal
 * \brief Merge fence-history coming from remote into local history
 *
 * \param[in] history   Hash-table holding remote history to be merged in
 */
static void
stonith_merge_in_history_list(GHashTable *history)
{
    GHashTableIter iter;
    remote_fencing_op_t *op = NULL;
    gboolean updated = FALSE;

    if (!history) {
        return;
    }

    init_stonith_remote_op_hash_table(&stonith_remote_op_list);

    g_hash_table_iter_init(&iter, history);
    while (g_hash_table_iter_next(&iter, NULL, (void **)&op)) {
        remote_fencing_op_t *stored_op =
            g_hash_table_lookup(stonith_remote_op_list, op->id);

        if (stored_op) {
            continue; // Skip existent (@TODO state-merging might be desirable)
        }

        updated = TRUE;
        g_hash_table_iter_steal(&iter);
        g_hash_table_insert(stonith_remote_op_list, op->id, op);
        /* we could trim the history here but if we bail
         * out after trim we might miss more recent entries
         * of those that might still be in the list
         * if we don't bail out trimming once is more
         * efficient and memory overhead is minimal as
         * we are just moving pointers from one hash to
         * another
         */
    }
    stonith_fence_history_trim();
    if (updated) {
        do_stonith_notify(0, T_STONITH_NOTIFY_HISTORY, 0, NULL);
    }
    g_hash_table_destroy(history); /* remove what is left */
}
Example #4
0
static void remote_op_done(remote_fencing_op_t *op, xmlNode *data, int rc) 
{
    xmlNode *reply = NULL;
    xmlNode *local_data = NULL;
    xmlNode *notify_data = NULL;

    op->completed = time(NULL);

    if(op->query_timer) {
        g_source_remove(op->query_timer);
        op->query_timer = 0;
    }
    if(op->op_timer) {
        g_source_remove(op->op_timer);
        op->op_timer = 0;
    }

    if(data == NULL) {
        data = create_xml_node(NULL, "remote-op");
        local_data = data;
    } else {
        op->delegate = crm_element_value_copy(data, F_ORIG);
    }

    crm_xml_add_int(data, "state", op->state);
    crm_xml_add(data, F_STONITH_TARGET,    op->target);
    crm_xml_add(data, F_STONITH_OPERATION, op->action); 

    if(op->request != NULL) {
        reply = stonith_construct_reply(op->request, NULL, data, rc);
        crm_xml_add(reply, F_STONITH_DELEGATE,  op->delegate);
        do_crm_log(rc==pcmk_ok?LOG_NOTICE:LOG_ERR,
               "Operation %s of %s by %s for %s[%s]: %s",
               op->action, op->target, op->delegate?op->delegate:"<no-one>",
               op->originator, op->client_id, pcmk_strerror(rc));

    } else {
        crm_err("Already sent notifications for '%s of %s by %s' (op=%s, for=%s, state=%d): %s",
                op->action, op->target, op->delegate, op->id, op->client_id, op->state,
                pcmk_strerror(rc));
        return;
    }

    if(reply) {
        do_local_reply(reply, op->client_id, op->call_options & st_opt_sync_call, FALSE);
    }

    /* Do notification with a clean data object */
    notify_data = create_xml_node(NULL, T_STONITH_NOTIFY_FENCE);
    crm_xml_add_int(notify_data, "state", op->state);
    crm_xml_add_int(notify_data, F_STONITH_RC,    rc);
    crm_xml_add(notify_data, F_STONITH_TARGET,    op->target);
    crm_xml_add(notify_data, F_STONITH_OPERATION, op->action); 
    crm_xml_add(notify_data, F_STONITH_DELEGATE,  op->delegate);
    crm_xml_add(notify_data, F_STONITH_REMOTE,    op->id);
    crm_xml_add(notify_data, F_STONITH_ORIGIN,    op->originator);
    crm_xml_add(notify_data, F_STONITH_CLIENTID,  op->client_id);
    crm_xml_add(notify_data, F_STONITH_CLIENTNAME,  op->client_name);

    do_stonith_notify(0, T_STONITH_NOTIFY_FENCE, rc, notify_data, NULL);

    free_xml(notify_data);
    free_xml(local_data);
    free_xml(reply);

    /* Free non-essential parts of the record
     * Keep the record around so we can query the history
     */
    if(op->query_results) {
        g_list_free_full(op->query_results, free_remote_query);
        op->query_results = NULL;
    }

    if(op->request) {
        free_xml(op->request);
        op->request = NULL;
    }
}