示例#1
0
/*!
 * \internal
 * \brief Check whether a directory or file is writable by the cluster daemon
 *
 * Return TRUE if either the cluster daemon user or cluster daemon group has
 * write permission on a specified file or directory.
 *
 * \param[in] dir      Directory to check (this argument must be specified, and
 *                     the directory must exist)
 * \param[in] file     File to check (only the directory will be checked if this
 *                     argument is not specified or the file does not exist)
 *
 * \return TRUE if target is writable by cluster daemon, FALSE otherwise
 */
bool
pcmk__daemon_can_write(const char *dir, const char *file)
{
    int s_res = 0;
    struct stat buf;
    char *full_file = NULL;
    const char *target = NULL;

    // Caller must supply directory
    CRM_ASSERT(dir != NULL);

    // If file is given, check whether it exists as a regular file
    if (file != NULL) {
        full_file = crm_concat(dir, file, '/');
        target = full_file;

        s_res = stat(full_file, &buf);
        if (s_res < 0) {
            crm_notice("%s not found: %s", target, pcmk_strerror(errno));
            free(full_file);
            full_file = NULL;
            target = NULL;

        } else if (S_ISREG(buf.st_mode) == FALSE) {
            crm_err("%s must be a regular file " CRM_XS " st_mode=0%lo",
                    target, (unsigned long) buf.st_mode);
            free(full_file);
            return FALSE;
        }
    }

    // If file is not given, ensure dir exists as directory
    if (target == NULL) {
        target = dir;
        s_res = stat(dir, &buf);
        if (s_res < 0) {
            crm_err("%s not found: %s", dir, pcmk_strerror(errno));
            return FALSE;

        } else if (S_ISDIR(buf.st_mode) == FALSE) {
            crm_err("%s must be a directory " CRM_XS " st_mode=0%lo",
                    dir, (unsigned long) buf.st_mode);
            return FALSE;
        }
    }

    if (!pcmk__daemon_user_can_write(target, &buf)
        && !pcmk__daemon_group_can_write(target, &buf)) {

        crm_err("%s must be owned and writable by either user %s or group %s "
                CRM_XS " st_mode=0%lo",
                target, CRM_DAEMON_USER, CRM_DAEMON_GROUP,
                (unsigned long) buf.st_mode);
        free(full_file);
        return FALSE;
    }

    free(full_file);
    return TRUE;
}
示例#2
0
void
cibadmin_op_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    exit_code = crm_errno2exit(rc);

    if (rc == -pcmk_err_schema_unchanged) {
        report_schema_unchanged();

    } else if (rc != pcmk_ok) {
        crm_warn("Call %s failed (%d): %s", cib_action, rc, pcmk_strerror(rc));
        fprintf(stderr, "Call %s failed (%d): %s\n", cib_action, rc, pcmk_strerror(rc));
        print_xml_output(output);

    } else if (safe_str_eq(cib_action, CIB_OP_QUERY) && output == NULL) {
        crm_err("Query returned no output");
        crm_log_xml_err(msg, "no output");

    } else if (output == NULL) {
        crm_info("Call passed");

    } else {
        crm_info("Call passed");
        print_xml_output(output);
    }

    if (call_id == request_id) {
        g_main_loop_quit(mainloop);

    } else {
        crm_info("Message was not the response we were looking for (%d vs. %d)",
                 call_id, request_id);
    }
}
示例#3
0
void
cibadmin_op_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    exit_code = rc;

    if (rc != 0) {
        crm_warn("Call %s failed (%d): %s", cib_action, rc, pcmk_strerror(rc));
        fprintf(stderr, "Call %s failed (%d): %s\n", cib_action, rc, pcmk_strerror(rc));
        print_xml_output(output);

    } else if (safe_str_eq(cib_action, CIB_OP_QUERY) && output == NULL) {
        crm_err("Output expected in query response");
        crm_log_xml_err(msg, "no output");

    } else if (output == NULL) {
        crm_info("Call passed");

    } else {
        crm_info("Call passed");
        print_xml_output(output);
    }

    if (call_id == request_id) {
        g_main_quit(mainloop);

    } else {
        crm_info("Message was not the response we were looking for (%d vs. %d", call_id,
                 request_id);
    }
}
示例#4
0
void
cibmon_diff(const char *event, xmlNode * msg)
{
    int rc = -1;
    const char *op = NULL;
    unsigned int log_level = LOG_INFO;

    xmlNode *diff = NULL;
    xmlNode *cib_last = NULL;
    xmlNode *update = get_message_xml(msg, F_CIB_UPDATE);

    if (msg == NULL) {
        crm_err("NULL update");
        return;
    }

    crm_element_value_int(msg, F_CIB_RC, &rc);
    op = crm_element_value(msg, F_CIB_OPERATION);
    diff = get_message_xml(msg, F_CIB_UPDATE_RESULT);

    if (rc < pcmk_ok) {
        log_level = LOG_WARNING;
        do_crm_log(log_level, "[%s] %s ABORTED: %s", event, op, pcmk_strerror(rc));
        return;
    }

    if (log_diffs) {
        xml_log_patchset(log_level, op, diff);
    }

    if (log_updates && update != NULL) {
        crm_log_xml_trace(update, "raw_update");
    }

    if (cib_copy != NULL) {
        cib_last = cib_copy;
        cib_copy = NULL;
        rc = cib_process_diff(op, cib_force_diff, NULL, NULL, diff, cib_last, &cib_copy, NULL);

        if (rc != pcmk_ok) {
            crm_debug("Update didn't apply, requesting full copy: %s", pcmk_strerror(rc));
            free_xml(cib_copy);
            cib_copy = NULL;
        }
    }

    if (cib_copy == NULL) {
        rc = cib->cmds->query(cib, NULL, &cib_copy, cib_scope_local | cib_sync_call);
    }

    if(rc == -EACCES) {
        crm_exit(CRM_EX_INSUFFICIENT_PRIV);
    }

    free_xml(cib_last);
}
示例#5
0
static void
crm_diff_update(const char *event, xmlNode * msg)
{
	int rc = -1;
	const char *op = NULL;
        long now = time(NULL);
        static int updates = 0;
        static mainloop_timer_t *refresh_timer = NULL;

        if(refresh_timer == NULL) {
            refresh_timer = mainloop_timer_add("refresh", 2000, FALSE, mon_trigger_refresh, NULL);
            refresh_trigger = mainloop_add_trigger(G_PRIORITY_LOW, mon_refresh_state, refresh_timer);
        }

        if (current_cib != NULL) {
		xmlNode *cib_last = current_cib;
		current_cib = NULL;

		rc = cib_apply_patch_event(msg, cib_last, &current_cib, LOG_DEBUG);
		free_xml(cib_last);

		switch(rc) {
			case -pcmk_err_diff_resync:
			case -pcmk_err_diff_failed:
                            crm_warn("[%s] %s Patch aborted: %s (%d)", event, op, pcmk_strerror(rc), rc);
                            break;
			case pcmk_ok:
                            updates++;
                            break;
			default:
                            crm_notice("[%s] %s ABORTED: %s (%d)", event, op, pcmk_strerror(rc), rc);
                            break;
		}
	}

	if (current_cib == NULL) {
		current_cib = get_cib_copy(cib);
	}

    /* Refresh
     * - immediately if the last update was more than 5s ago
     * - every 10 updates
     * - at most 2s after the last update
     */
    if (updates > 10 || (now - last_refresh) > (reconnect_msec / 1000)) {
        mon_refresh_state(refresh_timer);
        updates = 0;

    } else {
        mainloop_set_trigger(refresh_trigger);
        mainloop_timer_start(refresh_timer);
    }
}
示例#6
0
int
do_init(void)
{
    int rc = pcmk_ok;

    the_cib = cib_new();
    rc = the_cib->cmds->signon(the_cib, crm_system_name, cib_command);
    if (rc != pcmk_ok) {
        crm_err("Signon to CIB failed: %s", pcmk_strerror(rc));
        fprintf(stderr, "Signon to CIB failed: %s\n", pcmk_strerror(rc));
    }

    return rc;
}
示例#7
0
void
tengine_stonith_callback(stonith_t * stonith, stonith_callback_data_t * data)
{
    char *uuid = NULL;
    int target_rc = -1;
    int stonith_id = -1;
    int transition_id = -1;
    crm_action_t *action = NULL;
    struct st_fail_rec *rec = NULL;
    int call_id = data->call_id;
    int rc = data->rc;
    char *userdata = data->userdata;

    CRM_CHECK(userdata != NULL, return);
    crm_notice("Stonith operation %d/%s: %s (%d)", call_id, (char *)userdata,
               pcmk_strerror(rc), rc);

    if (AM_I_DC == FALSE) {
        return;
    }

    /* crm_info("call=%d, optype=%d, node_name=%s, result=%d, node_list=%s, action=%s", */
    /*       op->call_id, op->optype, op->node_name, op->op_result, */
    /*       (char *)op->node_list, op->private_data); */

    /* filter out old STONITH actions */
    CRM_CHECK(decode_transition_key(userdata, &uuid, &transition_id, &stonith_id, &target_rc),
              crm_err("Invalid event detected");
              goto bail;
        );
示例#8
0
qb_ipcs_service_t *
mainloop_add_ipc_server(const char *name, enum qb_ipc_type type,
                        struct qb_ipcs_service_handlers * callbacks)
{
    int rc = 0;
    qb_ipcs_service_t *server = NULL;

    if (gio_map == NULL) {
        gio_map = qb_array_create_2(64, sizeof(struct gio_to_qb_poll), 1);
    }

    crm_client_init();
    server = qb_ipcs_create(name, 0, pick_ipc_type(type), callbacks);

#ifdef HAVE_IPCS_GET_BUFFER_SIZE
    /* All clients should use at least ipc_buffer_max as their buffer size */
    qb_ipcs_enforce_buffer_size(server, crm_ipc_default_buffer_size());
#endif

    qb_ipcs_poll_handlers_set(server, &gio_poll_funcs);

    rc = qb_ipcs_run(server);
    if (rc < 0) {
        crm_err("Could not start %s IPC server: %s (%d)", name, pcmk_strerror(rc), rc);
        return NULL;
    }

    return server;
}
示例#9
0
文件: throttle.c 项目: krig/pacemaker
static bool throttle_load_avg(float *load)
{
    char buffer[256];
    FILE *stream = NULL;
    const char *loadfile = "/proc/loadavg";

    if(load == NULL) {
        return FALSE;
    }

    stream = fopen(loadfile, "r");
    if(stream == NULL) {
        int rc = errno;
        crm_warn("Couldn't read %s: %s (%d)", loadfile, pcmk_strerror(rc), rc);
        return FALSE;
    }

    if(fgets(buffer, sizeof(buffer), stream)) {
        char *nl = strstr(buffer, "\n");

        /* Grab the 1-minute average, ignore the rest */
        *load = strtof(buffer, NULL);
        if(nl) { nl[0] = 0; }

        crm_debug("Current load is %f (full: %s)", *load, buffer);
        fclose(stream);
        return TRUE;
    }

    fclose(stream);
    return FALSE;
}
示例#10
0
文件: throttle.c 项目: krig/pacemaker
int throttle_num_cores(void)
{
    static int cores = 0;
    char buffer[256];
    FILE *stream = NULL;
    const char *cpufile = "/proc/cpuinfo";

    if(cores) {
        return cores;
    }
    stream = fopen(cpufile, "r");
    if(stream == NULL) {
        int rc = errno;
        crm_warn("Couldn't read %s, assuming a single processor: %s (%d)", cpufile, pcmk_strerror(rc), rc);
        return 1;
    }

    while (fgets(buffer, sizeof(buffer), stream)) {
        if(strstr(buffer, "processor") == buffer) {
            cores++;
        }
    }

    fclose(stream);

    if(cores == 0) {
        crm_warn("No processors found in %s, assuming 1", cpufile);
        return 1;
    }

    return cores;
}
示例#11
0
static bool
pcmk__daemon_group_can_write(const char *target_name, struct stat *target_stat)
{
    struct group *sys_grp = NULL;

    errno = 0;
    sys_grp = getgrnam(CRM_DAEMON_GROUP);
    if (sys_grp == NULL) {
        crm_notice("Could not find group %s: %s",
                   CRM_DAEMON_GROUP, pcmk_strerror(errno));
        return FALSE;
    }

    if (target_stat->st_gid != sys_grp->gr_gid) {
        crm_notice("%s is not owned by group %s " CRM_XS " uid %d != %d",
                   target_name, CRM_DAEMON_GROUP,
                   sys_grp->gr_gid, target_stat->st_gid);
        return FALSE;
    }

    if ((target_stat->st_mode & (S_IRGRP | S_IWGRP)) == 0) {
        crm_notice("%s is not readable and writable by group %s "
                   CRM_XS " st_mode=0%lo",
                   target_name, CRM_DAEMON_GROUP,
                   (unsigned long) target_stat->st_mode);
        return FALSE;
    }
    return TRUE;
}
示例#12
0
static bool
pcmk__daemon_user_can_write(const char *target_name, struct stat *target_stat)
{
    struct passwd *sys_user = NULL;

    errno = 0;
    sys_user = getpwnam(CRM_DAEMON_USER);
    if (sys_user == NULL) {
        crm_notice("Could not find user %s: %s",
                   CRM_DAEMON_USER, pcmk_strerror(errno));
        return FALSE;
    }
    if (target_stat->st_uid != sys_user->pw_uid) {
        crm_notice("%s is not owned by user %s " CRM_XS " uid %d != %d",
                   target_name, CRM_DAEMON_USER, sys_user->pw_uid,
                   target_stat->st_uid);
        return FALSE;
    }
    if ((target_stat->st_mode & (S_IRUSR | S_IWUSR)) == 0) {
        crm_notice("%s is not readable and writable by user %s "
                   CRM_XS " st_mode=0%lo",
                   target_name, CRM_DAEMON_USER,
                   (unsigned long) target_stat->st_mode);
        return FALSE;
    }
    return TRUE;
}
示例#13
0
文件: utils.c 项目: beekhof/pacemaker
int
crm_user_lookup(const char *name, uid_t * uid, gid_t * gid)
{
    int rc = pcmk_ok;
    char *buffer = NULL;
    struct passwd pwd;
    struct passwd *pwentry = NULL;

    buffer = calloc(1, PW_BUFFER_LEN);
    rc = getpwnam_r(name, &pwd, buffer, PW_BUFFER_LEN, &pwentry);
    if (pwentry) {
        if (uid) {
            *uid = pwentry->pw_uid;
        }
        if (gid) {
            *gid = pwentry->pw_gid;
        }
        crm_trace("User %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);

    } else {
        rc = rc? -rc : -EINVAL;
        crm_info("User %s lookup: %s", name, pcmk_strerror(rc));
    }

    free(buffer);
    return rc;
}
示例#14
0
static void
remote_config_check(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    if (rc != pcmk_ok) {
        crm_err("Query resulted in an error: %s", pcmk_strerror(rc));

        if (rc == -EACCES || rc == -pcmk_err_schema_validation) {
            crm_err("The cluster is mis-configured - shutting down and staying down");
        }

    } else {
        lrmd_t * lrmd = (lrmd_t *)user_data;
        crm_time_t *now = crm_time_new(NULL);
        GHashTable *config_hash = g_hash_table_new_full(
            crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);

        crm_debug("Call %d : Parsing CIB options", call_id);
        
        unpack_instance_attributes(
            output, output, XML_CIB_TAG_PROPSET, NULL, config_hash, CIB_OPTIONS_FIRST, FALSE, now);

        /* Now send it to the remote peer */
        remote_proxy_check(lrmd, config_hash);

        g_hash_table_destroy(config_hash);
        crm_time_free(now);
    }
}
示例#15
0
static void
node_list_update_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    fsa_data_t *msg_data = NULL;

    if(call_id < pcmk_ok) {
        crm_err("Node list update failed: %s (%d)", pcmk_strerror(call_id), call_id);
        crm_log_xml_debug(msg, "update:failed");
        register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);

    } else if(rc < pcmk_ok) {
        crm_err("Node update %d failed: %s (%d)", call_id, pcmk_strerror(rc), rc);
        crm_log_xml_debug(msg, "update:failed");
        register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
    }
}
void
cib_action_updated(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    if (rc < pcmk_ok) {
        crm_err("Update %d FAILED: %s", call_id, pcmk_strerror(rc));
    }
}
示例#17
0
文件: ipc.c 项目: bcavanagh/pacemaker
long
crm_ipc_read(crm_ipc_t *client) 
{
    CRM_ASSERT(client != NULL);
    CRM_ASSERT(client->ipc != NULL);
    CRM_ASSERT(client->buffer != NULL);

    client->buffer[0] = 0;
    client->msg_size = qb_ipcc_event_recv(client->ipc, client->buffer, client->buf_size-1, 0);
    if(client->msg_size >= 0) {
        struct qb_ipc_response_header *header = (struct qb_ipc_response_header *)client->buffer;
        client->buffer[client->msg_size] = 0;

        crm_trace("Recieved %s event %d, size=%d, rc=%d, text: %.200s",
                  client->name, header->id, header->size, client->msg_size,
                  client->buffer+sizeof(struct qb_ipc_response_header));
    } else {
        crm_trace("No message from %s recieved: %s", client->name, pcmk_strerror(client->msg_size));
    }

    if(crm_ipc_connected(client) == FALSE || client->msg_size == -ENOTCONN) {
        crm_err("Connection to %s failed", client->name);
    }
    
    return client->msg_size;
}
示例#18
0
/*!
 * \brief Send a request to pacemaker-attrd to clear resource failure
 *
 * \param[in] ipc           Connection to pacemaker-attrd (NULL to use local connection)
 * \param[in] host          Affect only this host (or NULL for all hosts)
 * \param[in] resource      Name of resource to clear (or NULL for all)
 * \param[in] operation     Name of operation to clear (or NULL for all)
 * \param[in] interval_spec If operation is not NULL, its interval
 * \param[in] user_name     ACL user to pass to pacemaker-attrd
 * \param[in] options       attrd_opt_remote if host is a Pacemaker Remote node
 *
 * \return pcmk_ok if request was successfully submitted to pacemaker-attrd, else -errno
 */
int
attrd_clear_delegate(crm_ipc_t *ipc, const char *host, const char *resource,
                     const char *operation, const char *interval_spec,
                     const char *user_name, int options)
{
    int rc = pcmk_ok;
    xmlNode *clear_op = create_attrd_op(user_name);
    const char *interval_desc = NULL;
    const char *op_desc = NULL;

    crm_xml_add(clear_op, F_ATTRD_TASK, ATTRD_OP_CLEAR_FAILURE);
    crm_xml_add(clear_op, F_ATTRD_HOST, host);
    crm_xml_add(clear_op, F_ATTRD_RESOURCE, resource);
    crm_xml_add(clear_op, F_ATTRD_OPERATION, operation);
    crm_xml_add(clear_op, F_ATTRD_INTERVAL, interval_spec);
    crm_xml_add_int(clear_op, F_ATTRD_IS_REMOTE, is_set(options, attrd_opt_remote));

    rc = send_attrd_op(ipc, clear_op);
    free_xml(clear_op);

    if (operation) {
        interval_desc = interval_spec? interval_spec : "nonrecurring";
        op_desc = operation;
    } else {
        interval_desc = "all";
        op_desc = "operations";
    }
    crm_debug("Asked pacemaker-attrd to clear failure of %s %s for %s on %s: %s (%d)",
              interval_desc, op_desc, (resource? resource : "all resources"),
              (host? host : "all nodes"), pcmk_strerror(rc), rc);
    return rc;
}
示例#19
0
static void
pcmk_child_exit(mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode)
{
    pcmk_child_t *child = mainloop_child_userdata(p);
    const char *name = mainloop_child_name(p);

    if (signo) {
        crm_notice("Child process %s terminated with signal %d (pid=%d, core=%d)",
                   name, signo, pid, core);

    } else {
        do_crm_log(exitcode == 0 ? LOG_INFO : LOG_ERR,
                   "Child process %s (%d) exited: %s (%d)", name, pid, pcmk_strerror(exitcode), exitcode);
    }

    if (exitcode == 100) {
        crm_warn("Pacemaker child process %s no longer wishes to be respawned. "
                 "Shutting ourselves down.", name);
        child->respawn = FALSE;
        fatal_error = TRUE;
        pcmk_shutdown(15);
    }

    pcmk_process_exit(child);
}
示例#20
0
static void
stonith_notify_client(gpointer key, gpointer value, gpointer user_data)
{

    xmlNode *update_msg = user_data;
    crm_client_t *client = value;
    const char *type = NULL;

    CRM_CHECK(client != NULL, return);
    CRM_CHECK(update_msg != NULL, return);

    type = crm_element_value(update_msg, F_SUBTYPE);
    CRM_CHECK(type != NULL, crm_log_xml_err(update_msg, "notify"); return);

    if (client->ipcs == NULL) {
        crm_trace("Skipping client with NULL channel");
        return;
    }

    if (client->options & get_stonith_flag(type)) {
        int rc = crm_ipcs_send(client, 0, update_msg, crm_ipc_server_event | crm_ipc_server_error);

        if (rc <= 0) {
            crm_warn("%s notification of client %s.%.6s failed: %s (%d)",
                     type, crm_client_name(client), client->id, pcmk_strerror(rc), rc);
        } else {
            crm_trace("Sent %s notification to client %s.%.6s", type, crm_client_name(client),
                      client->id);
        }
    }
}
示例#21
0
int
query_node_uuid(cib_t * the_cib, const char *uname, char **uuid, int *is_remote_node)
{
    int rc = pcmk_ok;

    CRM_ASSERT(uname != NULL);
    CRM_ASSERT(uuid != NULL);

    rc = get_cluster_node_uuid(the_cib, uname, uuid);
    if (rc != pcmk_ok) {
        crm_debug("%s is not a cluster node, checking to see if remote-node", uname);
        rc = get_remote_node_uuid(the_cib, uname, uuid);
        if (rc != pcmk_ok) {
            crm_debug("%s is not a remote node either", uname);

        } else if (is_remote_node) {
            *is_remote_node = TRUE;
        }
    }

    if (rc != pcmk_ok) {
        crm_debug("Could not map name=%s to a UUID: %s\n", uname, pcmk_strerror(rc));
    } else {
        crm_info("Mapped %s to %s", uname, *uuid);
    }

    return rc;
}
示例#22
0
int
query_node_uuid(cib_t * the_cib, const char *uname, char **uuid, int *is_remote_node)
{
    int rc = pcmk_ok;
    char *xpath_string;
    xmlNode *xml_search = NULL;

    CRM_ASSERT(uname != NULL);

    if (uuid) {
        *uuid = NULL;
    }
    if (is_remote_node) {
        *is_remote_node = FALSE;
    }

    xpath_string = crm_strdup_printf(XPATH_NODE, uname, uname, uname, uname);
    if (cib_internal_op(the_cib, CIB_OP_QUERY, NULL, xpath_string, NULL,
                        &xml_search, cib_sync_call|cib_scope_local|cib_xpath,
                        NULL) == pcmk_ok) {
        rc = get_uuid_from_result(xml_search, uuid, is_remote_node);
    } else {
        rc = -ENXIO;
    }
    free(xpath_string);
    free_xml(xml_search);

    if (rc != pcmk_ok) {
        crm_debug("Could not map node name '%s' to a UUID: %s",
                  uname, pcmk_strerror(rc));
    } else {
        crm_info("Mapped node name '%s' to UUID %s", uname, (uuid? *uuid : ""));
    }
    return rc;
}
示例#23
0
文件: main.c 项目: beekhof/pacemaker
stonith_t *
get_stonith_connection(void)
{
    if (stonith_api && stonith_api->state == stonith_disconnected) {
        stonith_api_delete(stonith_api);
        stonith_api = NULL;
    }

    if (!stonith_api) {
        int rc = 0;
        int tries = 10;

        stonith_api = stonith_api_new();
        do {
            rc = stonith_api->cmds->connect(stonith_api, "lrmd", NULL);
            if (rc == pcmk_ok) {
                stonith_api->cmds->register_notification(stonith_api,
                                                         T_STONITH_NOTIFY_DISCONNECT,
                                                         stonith_connection_destroy_cb);
                break;
            }
            sleep(1);
            tries--;
        } while (tries);

        if (rc) {
            crm_err("Unable to connect to stonith daemon to execute command. error: %s",
                    pcmk_strerror(rc));
            stonith_api_delete(stonith_api);
            stonith_api = NULL;
        }
    }
    return stonith_api;
}
示例#24
0
文件: ipc.c 项目: credativ/pacemaker
/*!
 * \brief Establish an IPC connection to a Pacemaker component
 *
 * \param[in] client  Connection instance obtained from crm_ipc_new()
 *
 * \return TRUE on success, FALSE otherwise (in which case errno will be set)
 */
bool
crm_ipc_connect(crm_ipc_t * client)
{
    client->need_reply = FALSE;
    client->ipc = qb_ipcc_connect(client->name, client->buf_size);

    if (client->ipc == NULL) {
        crm_debug("Could not establish %s connection: %s (%d)", client->name, pcmk_strerror(errno), errno);
        return FALSE;
    }

    client->pfd.fd = crm_ipc_get_fd(client);
    if (client->pfd.fd < 0) {
        crm_debug("Could not obtain file descriptor for %s connection: %s (%d)", client->name, pcmk_strerror(errno), errno);
        return FALSE;
    }

    qb_ipcc_context_set(client->ipc, client);

#ifdef HAVE_IPCS_GET_BUFFER_SIZE
    client->max_buf_size = qb_ipcc_get_buffer_size(client->ipc);
    if (client->max_buf_size > client->buf_size) {
        free(client->buffer);
        client->buffer = calloc(1, client->max_buf_size);
        client->buf_size = client->max_buf_size;
    }
#endif

    return TRUE;
}
示例#25
0
void
finalize_sync_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    CRM_LOG_ASSERT(-EPERM != rc);
    clear_bit(fsa_input_register, R_CIB_ASKED);
    if (rc != pcmk_ok) {
        do_crm_log((rc == -pcmk_err_old_data ? LOG_WARNING : LOG_ERR),
                   "Sync from %s failed: %s", (char *)user_data, pcmk_strerror(rc));

        /* restart the whole join process */
        register_fsa_error_adv(C_FSA_INTERNAL, I_ELECTION_DC, NULL, NULL, __FUNCTION__);

    } else if (AM_I_DC && fsa_state == S_FINALIZE_JOIN) {
        set_bit(fsa_input_register, R_HAVE_CIB);
        clear_bit(fsa_input_register, R_CIB_ASKED);

        /* make sure dc_uuid is re-set to us */
        if (check_join_state(fsa_state, __FUNCTION__) == FALSE) {
            crm_debug("Notifying %d clients of join-%d results",
                      crmd_join_phase_count(crm_join_integrated), current_join_id);
            g_hash_table_foreach(crm_peer_cache, finalize_join_for, NULL);
        }

    } else {
        crm_debug("No longer the DC in S_FINALIZE_JOIN: %s/%s",
                  AM_I_DC ? "DC" : "CRMd", fsa_state2string(fsa_state));
    }
}
示例#26
0
文件: utils.c 项目: beekhof/pacemaker
void
crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile)
{
    int rc;
    long pid;
    const char *devnull = "/dev/null";

    if (daemonize == FALSE) {
        return;
    }

    /* Check before we even try... */
    rc = crm_pidfile_inuse(pidfile, 1, name);
    if(rc < pcmk_ok && rc != -ENOENT) {
        pid = crm_read_pidfile(pidfile);
        crm_err("%s: already running [pid %ld in %s]", name, pid, pidfile);
        printf("%s: already running [pid %ld in %s]\n", name, pid, pidfile);
        crm_exit(rc);
    }

    pid = fork();
    if (pid < 0) {
        fprintf(stderr, "%s: could not start daemon\n", name);
        crm_perror(LOG_ERR, "fork");
        crm_exit(EINVAL);

    } else if (pid > 0) {
        crm_exit(pcmk_ok);
    }

    rc = crm_lock_pidfile(pidfile, name);
    if(rc < pcmk_ok) {
        crm_err("Could not lock '%s' for %s: %s (%d)", pidfile, name, pcmk_strerror(rc), rc);
        printf("Could not lock '%s' for %s: %s (%d)\n", pidfile, name, pcmk_strerror(rc), rc);
        crm_exit(rc);
    }

    umask(S_IWGRP | S_IWOTH | S_IROTH);

    close(STDIN_FILENO);
    (void)open(devnull, O_RDONLY);      /* Stdin:  fd 0 */
    close(STDOUT_FILENO);
    (void)open(devnull, O_WRONLY);      /* Stdout: fd 1 */
    close(STDERR_FILENO);
    (void)open(devnull, O_WRONLY);      /* Stderr: fd 2 */
}
示例#27
0
static void
attrd_cib_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    int level = LOG_ERR;
    GHashTableIter iter;
    const char *peer = NULL;
    attribute_value_t *v = NULL;

    char *name = user_data;
    attribute_t *a = g_hash_table_lookup(attributes, name);

    if(a == NULL) {
        crm_info("Attribute %s no longer exists", name);
        goto done;
    }

    a->update = 0;
    if (rc == pcmk_ok && call_id < 0) {
        rc = call_id;
    }

    switch (rc) {
        case pcmk_ok:
            level = LOG_INFO;
            last_cib_op_done = call_id;
            break;
        case -pcmk_err_diff_failed:    /* When an attr changes while the CIB is syncing */
        case -ETIME:           /* When an attr changes while there is a DC election */
        case -ENXIO:           /* When an attr changes while the CIB is syncing a
                                *   newer config from a node that just came up
                                */
            level = LOG_WARNING;
            break;
    }

    do_crm_log(level, "Update %d for %s: %s (%d)", call_id, name, pcmk_strerror(rc), rc);

    g_hash_table_iter_init(&iter, a->values);
    while (g_hash_table_iter_next(&iter, (gpointer *) & peer, (gpointer *) & v)) {
        crm_notice("Update %d for %s[%s]=%s: %s (%d)", call_id, a->id, peer, v->requested, pcmk_strerror(rc), rc);

        if(rc == pcmk_ok) {
            free(v->stored);
            v->stored = v->requested;
            v->requested = NULL;

        } else {
            free(v->requested);
            v->requested = NULL;
            a->changed = TRUE; /* Attempt write out again */
        }
    }
  done:
    free(name);
    if(a && a->changed && election_state(writer) == election_won) {
        write_attribute(a);
    }
}
示例#28
0
void
cibadmin_op_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void *user_data)
{
    char *admin_input_xml = NULL;

    exit_code = rc;

    if (output != NULL) {
        admin_input_xml = dump_xml_formatted(output);
    }

    if (safe_str_eq(cib_action, CIB_OP_ISMASTER) && rc != pcmk_ok) {
        crm_info("CIB on %s is _not_ the master instance", host ? host : "localhost");
        fprintf(stderr, "CIB on %s is _not_ the master instance\n", host ? host : "localhost");

    } else if (safe_str_eq(cib_action, CIB_OP_ISMASTER)) {
        crm_info("CIB on %s _is_ the master instance", host ? host : "localhost");
        fprintf(stderr, "CIB on %s _is_ the master instance\n", host ? host : "localhost");

    } else if (rc != 0) {
        crm_warn("Call %s failed (%d): %s", cib_action, rc, pcmk_strerror(rc));
        fprintf(stderr, "Call %s failed (%d): %s\n", cib_action, rc, pcmk_strerror(rc));
        fprintf(stdout, "%s\n", crm_str(admin_input_xml));

    } else if (safe_str_eq(cib_action, CIB_OP_QUERY) && output == NULL) {
        crm_err("Output expected in query response");
        crm_log_xml_err(msg, "no output");

    } else if (output == NULL) {
        crm_info("Call passed");

    } else {
        crm_info("Call passed");
        fprintf(stdout, "%s\n", crm_str(admin_input_xml));
    }
    free(admin_input_xml);

    if (call_id == request_id) {
        g_main_quit(mainloop);

    } else {
        crm_info("Message was not the response we were looking for (%d vs. %d", call_id,
                 request_id);
    }
}
示例#29
0
static void
pcmk_panic_local(void) 
{
    int rc = pcmk_ok;
    uid_t uid = geteuid();
    pid_t ppid = getppid();

    if(uid != 0 && ppid > 1) {
        /* We're a non-root pacemaker daemon (cib, crmd, pengine,
         * attrd, etc) with the original pacemakerd parent
         *
         * Of these, only crmd is likely to be initiating resets
         */
        do_crm_log_always(LOG_EMERG, "Signaling parent %d to panic", ppid);
        crm_exit(pcmk_err_panic);
        return;

    } else if (uid != 0) {
        /*
         * No permissions and no pacemakerd parent to escalate to
         * Track down the new pacakerd process and send a signal instead
         */
        union sigval signal_value;

        memset(&signal_value, 0, sizeof(signal_value));
        ppid = crm_procfs_pid_of("pacemakerd");
        do_crm_log_always(LOG_EMERG, "Signaling pacemakerd(%d) to panic", ppid);

        if(ppid > 1 && sigqueue(ppid, SIGQUIT, signal_value) < 0) {
            crm_perror(LOG_EMERG, "Cannot signal pacemakerd(%d) to panic", ppid);
        }
        /* The best we can do now is die */
        crm_exit(pcmk_err_panic);
        return;
    }

    /* We're either pacemakerd, or a pacemaker daemon running as root */

    if (safe_str_eq("crash", getenv("PCMK_panic_action"))) {
        sysrq_trigger('c');
    } else {
        sysrq_trigger('b');
    }
    /* reboot(RB_HALT_SYSTEM); rc = errno; */
    reboot(RB_AUTOBOOT);
    rc = errno;

    do_crm_log_always(LOG_EMERG, "Reboot failed, escalating to %d: %s (%d)", ppid, pcmk_strerror(rc), rc);

    if(ppid > 1) {
        /* child daemon */
        exit(pcmk_err_panic);
    } else {
        /* pacemakerd or orphan child */
        exit(DAEMON_RESPAWN_STOP);
    }
}
示例#30
0
static int
internal_tcp_connect_async(int sock,
                           const struct sockaddr *addr, socklen_t addrlen, int timeout /* ms */ ,
                           int *timer_id, void *userdata, void (*callback) (void *userdata, int sock))
{
    int rc = 0;
    int interval = 500;
    int timer;
    struct tcp_async_cb_data *cb_data = NULL;

    rc = crm_set_nonblocking(sock);
    if (rc < 0) {
        crm_warn("Could not set socket non-blocking: %s " CRM_XS " rc=%d",
                 pcmk_strerror(rc), rc);
        close(sock);
        return -1;
    }

    rc = connect(sock, addr, addrlen);
    if (rc < 0 && (errno != EINPROGRESS) && (errno != EAGAIN)) {
        crm_perror(LOG_WARNING, "connect");
        return -1;
    }

    cb_data = calloc(1, sizeof(struct tcp_async_cb_data));
    cb_data->userdata = userdata;
    cb_data->callback = callback;
    cb_data->sock = sock;
    cb_data->timeout = timeout;
    cb_data->start = time(NULL);

    if (rc == 0) {
        /* The connect was successful immediately, we still return to mainloop
         * and let this callback get called later. This avoids the user of this api
         * to have to account for the fact the callback could be invoked within this
         * function before returning. */
        cb_data->success = TRUE;
        interval = 1;
    }

    /* Check connect finished is mostly doing a non-block poll on the socket
     * to see if we can read/write to it. Once we can, the connect has completed.
     * This method allows us to connect to the server without blocking mainloop.
     *
     * This is a poor man's way of polling to see when the connection finished.
     * At some point we should figure out a way to use a mainloop fd callback for this.
     * Something about the way mainloop is currently polling prevents this from working at the
     * moment though. */
    crm_trace("Scheduling check in %dms for whether connect to fd %d finished",
              interval, sock);
    timer = g_timeout_add(interval, check_connect_finished, cb_data);
    if (timer_id) {
        *timer_id = timer;
    }

    return 0;
}