Example #1
0
int
write_local_hb_uuid(const char *new_value)
{
    int fd;
    int rc = 0;
    cl_uuid_t uuid;
    char *buffer = strdup(new_value);

    rc = cl_uuid_parse(buffer, &uuid);
    if (rc != 0) {
        fprintf(stderr, "Invalid ASCII UUID supplied: [%s]\n", new_value);
        fprintf(stderr, "ASCII UUIDs must be of the form"
                " XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" " and contain only letters and digits\n");
        return 5;
    }

    if ((fd = open(UUID_FILE, O_WRONLY | O_SYNC | O_CREAT, 0644)) < 0) {
        crm_perror(LOG_ERR, "Could not open %s", UUID_FILE);
        return 6;
    }

    if (write(fd, uuid.uuid, UUID_LEN) != UUID_LEN) {
        crm_perror(LOG_ERR, "Could not write UUID to %s", UUID_FILE);
        rc = 7;
    }

    if (close(fd) < 0) {
        crm_perror(LOG_ERR, "Could not close %s", UUID_FILE);
        rc = 8;
    }
    return rc;
}
Example #2
0
/*!
 * \internal
 * \brief Flush and sync a directory to disk
 *
 * \param[in] name Directory to flush and sync
 * \note This function logs errors but does not return them to the caller
 */
void
crm_sync_directory(const char *name)
{
    int fd;
    DIR *directory;

    directory = opendir(name);
    if (directory == NULL) {
        crm_perror(LOG_ERR, "Could not open %s for syncing", name);
        return;
    }

    fd = dirfd(directory);
    if (fd < 0) {
        crm_perror(LOG_ERR, "Could not obtain file descriptor for %s", name);
        return;
    }

    if (fsync(fd) < 0) {
        crm_perror(LOG_ERR, "Could not sync %s", name);
    }
    if (closedir(directory) < 0) {
        crm_perror(LOG_ERR, "Could not close %s after fsync", name);
    }
}
Example #3
0
/*!
 * \brief Create a new election object
 *
 * Every node that wishes to participate in an election must create an election
 * object. Typically, this should be done once, at start-up. A caller should
 * only create a single election object.
 *
 * \param[in] name       Label for election (for logging)
 * \param[in] uname      Local node's name
 * \param[in] period_ms  How long to wait for all peers to vote
 * \param[in] cb         Function to call if local node wins election
 *
 * \return Newly allocated election object on success, NULL on error
 * \note The caller is responsible for freeing the returned value using
 *       election_fini().
 */
election_t *
election_init(const char *name, const char *uname, guint period_ms, GSourceFunc cb)
{
    election_t *e = NULL;

    static guint count = 0;

    CRM_CHECK(uname != NULL, return NULL);

    e = calloc(1, sizeof(election_t));
    if (e == NULL) {
        crm_perror(LOG_CRIT, "Cannot create election");
        return NULL;
    }

    e->uname = strdup(uname);
    if (e->uname == NULL) {
        crm_perror(LOG_CRIT, "Cannot create election");
        free(e);
        return NULL;
    }

    e->name = name? crm_strdup_printf("election-%s", name)
                  : crm_strdup_printf("election-%u", count++);
    e->cb = cb;
    e->timeout = mainloop_timer_add(e->name, period_ms, FALSE,
                                    election_timer_cb, e);
    crm_trace("Created %s", e->name);
    return e;
}
Example #4
0
int
crm_pid_active(long pid, const char *daemon)
{
    static int have_proc_pid = 0;

    if(have_proc_pid == 0) {
        char proc_path[PATH_MAX], exe_path[PATH_MAX];

        /* check to make sure pid hasn't been reused by another process */
        snprintf(proc_path, sizeof(proc_path), "/proc/%lu/exe", (long unsigned int)getpid());

        have_proc_pid = 1;
        if(readlink(proc_path, exe_path, PATH_MAX - 1) < 0) {
            have_proc_pid = -1;
        }
    }

    if (pid <= 0) {
        return -1;

    } else if (kill(pid, 0) < 0 && errno == ESRCH) {
        return 0;

    } else if(daemon == NULL || have_proc_pid == -1) {
        return 1;

    } else {
        int rc = 0;
        char proc_path[PATH_MAX], exe_path[PATH_MAX], myexe_path[PATH_MAX];

        /* check to make sure pid hasn't been reused by another process */
        snprintf(proc_path, sizeof(proc_path), "/proc/%lu/exe", pid);

        rc = readlink(proc_path, exe_path, PATH_MAX - 1);
        if (rc < 0 && errno == EACCES) {
            crm_perror(LOG_INFO, "Could not read from %s", proc_path);
            return 1;
        } else if (rc < 0) {
            crm_perror(LOG_ERR, "Could not read from %s", proc_path);
            return 0;
        }
        

        exe_path[rc] = 0;

        if(daemon[0] != '/') {
            rc = snprintf(myexe_path, sizeof(proc_path), CRM_DAEMON_DIR"/%s", daemon);
            myexe_path[rc] = 0;
        } else {
            rc = snprintf(myexe_path, sizeof(proc_path), "%s", daemon);
            myexe_path[rc] = 0;
        }
        
        if (strcmp(exe_path, myexe_path) == 0) {
            return 1;
        }
    }

    return 0;
}
Example #5
0
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_perror(LOG_INFO, "Could not establish %s connection", client->name);
        return FALSE;
    }

    client->pfd.fd = crm_ipc_get_fd(client);
    if (client->pfd.fd < 0) {
        crm_perror(LOG_INFO, "Could not obtain file descriptor for %s connection", client->name);
        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;
}
Example #6
0
char *
get_shadow_file(const char *suffix)
{
    char *cib_home = NULL;
    char *fullname = NULL;
    char *name = crm_concat("shadow", suffix, '.');
    const char *dir = getenv("CIB_shadow_dir");

    if (dir == NULL) {
        uid_t uid = geteuid();
        struct passwd *pwent = getpwuid(uid);
        const char *user = NULL;

        if (pwent) {
            user = pwent->pw_name;
        } else {
            user = getenv("USER");
            crm_perror(LOG_ERR,
                       "Assuming %s because cannot get user details for user ID %d",
                       (user? user : "******"), uid);
        }

        if (safe_str_eq(user, "root") || safe_str_eq(user, CRM_DAEMON_USER)) {
            dir = CRM_CONFIG_DIR;

        } else {
            const char *home = NULL;

            if ((home = getenv("HOME")) == NULL) {
                if (pwent) {
                    home = pwent->pw_dir;
                }
            }

            dir = crm_get_tmpdir();
            if (home && home[0] == '/') {
                int rc = 0;

                cib_home = crm_concat(home, ".cib", '/');

                rc = mkdir(cib_home, 0700);
                if (rc < 0 && errno != EEXIST) {
                    crm_perror(LOG_ERR, "Couldn't create user-specific shadow directory: %s",
                               cib_home);
                    errno = 0;

                } else {
                    dir = cib_home;
                }
            }
        }
    }

    fullname = crm_concat(dir, name, '/');
    free(cib_home);
    free(name);

    return fullname;
}
Example #7
0
static int
bind_and_listen(struct addrinfo *addr)
{
    int optval;
    int fd;
    int rc;
    char buffer[256] = { 0, };

    if (addr->ai_family == AF_INET6) {
        struct sockaddr_in6 *addr_in = (struct sockaddr_in6 *)(void*)addr->ai_addr;
        inet_ntop(addr->ai_family, &addr_in->sin6_addr, buffer, DIMOF(buffer));

    } else {
        struct sockaddr_in *addr_in = (struct sockaddr_in *)(void*)addr->ai_addr;
        inet_ntop(addr->ai_family, &addr_in->sin_addr, buffer, DIMOF(buffer));
    }

    crm_trace("Attempting to bind on address %s", buffer);

    fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    if (fd < 0) {
        return -1;
    }

    /* reuse address */
    optval = 1;
    rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
    if (rc < 0) {
        crm_perror(LOG_INFO, "Couldn't allow the reuse of local addresses by our remote listener, bind address %s", buffer);
        close(fd);
        return -1;
    }

    if (addr->ai_family == AF_INET6) {
        optval = 0;
        rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
        if (rc < 0) {
            crm_perror(LOG_INFO, "Couldn't disable IPV6 only on address %s", buffer);
            close(fd);
            return -1;
        }
    }

    if (bind(fd, addr->ai_addr, addr->ai_addrlen) != 0) {
        close(fd);
        return -1;
    }

    if (listen(fd, 10) == -1) {
        crm_err("Can not start listen on address %s", buffer);
        close(fd);
        return -1;
    }

    crm_notice("Listening on address %s", buffer);

    return fd;
}
Example #8
0
gboolean
crm_log_init(
    const char *entity, int level, gboolean coredir, gboolean to_stderr,
    int argc, char **argv)
{
	/* Redirect messages from glib functions to our handler */
/*  	cl_malloc_forced_for_glib(); */
#ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
	glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL);
#endif
	
	/* and for good measure... - this enum is a bit field (!) */
	g_log_set_always_fatal((GLogLevelFlags)0); /*value out of range*/
	
	crm_system_name = entity;
	setenv("PCMK_service", crm_system_name, 1);
	cl_log_set_entity(entity);
	if(argc == 0) {
	    /* Nuke any syslog activity */
	    unsetenv("HA_logfacility");

	} else if(getenv("HA_logfacility") == NULL) {
	    /* Set a default */
	    cl_log_set_facility(HA_LOG_FACILITY);
	} /* else: picked up by crm_set_env_options() */
	
	if(coredir) {
	    int user = getuid();
	    struct passwd *pwent = NULL;
	    const char *base = HA_COREDIR;
	    
	    pwent = getpwuid(user);

	    if (chdir(base) < 0) {
		crm_perror(LOG_ERR, "Cannot change active directory to %s", base);

	    } else if (pwent == NULL) {
		crm_perror(LOG_ERR, "Cannot get name for uid: %d", user);

	    } else if (chdir(pwent->pw_name) < 0) {
		crm_perror(LOG_ERR, "Cannot change active directory to %s/%s", base, pwent->pw_name);

	    } else {
		crm_info("Changed active directory to %s/%s", base, pwent->pw_name);
	    }
	}
	
	set_crm_log_level(level);
	crm_set_env_options();

	cl_log_args(argc, argv);
	cl_log_enable_stderr(to_stderr);

	crm_signal(DEBUG_INC, alter_debug);
	crm_signal(DEBUG_DEC, alter_debug);

	return TRUE;
}
Example #9
0
static int
bind_and_listen(struct addrinfo *addr)
{
    int optval;
    int fd;
    int rc;
    char buffer[INET6_ADDRSTRLEN] = { 0, };

    crm_sockaddr2str(addr->ai_addr, buffer);
    crm_trace("Attempting to bind to address %s", buffer);

    fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    if (fd < 0) {
        crm_perror(LOG_ERR, "Listener socket creation failed");
        return -1;
    }

    /* reuse address */
    optval = 1;
    rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
    if (rc < 0) {
        crm_perror(LOG_ERR, "Local address reuse not allowed on %s", buffer);
        close(fd);
        return -1;
    }

    if (addr->ai_family == AF_INET6) {
        optval = 0;
        rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
        if (rc < 0) {
            crm_perror(LOG_INFO, "Couldn't disable IPV6-only on %s", buffer);
            close(fd);
            return -1;
        }
    }

    if (bind(fd, addr->ai_addr, addr->ai_addrlen) != 0) {
        crm_perror(LOG_ERR, "Cannot bind to %s", buffer);
        close(fd);
        return -1;
    }

    if (listen(fd, 10) == -1) {
        crm_perror(LOG_ERR, "Cannot listen on %s", buffer);
        close(fd);
        return -1;
    }
    return fd;
}
Example #10
0
static gboolean
stop_child(pcmk_child_t * child, int signal)
{
    if (signal == 0) {
        signal = SIGTERM;
    }

    if (child->command == NULL) {
        crm_debug("Nothing to do for child \"%s\"", child->name);
        return TRUE;
    }

    if (child->pid <= 0) {
        crm_trace("Client %s not running", child->name);
        return TRUE;
    }

    errno = 0;
    if (kill(child->pid, signal) == 0) {
        crm_notice("Stopping %s: Sent -%d to process %d", child->name, signal, child->pid);

    } else {
        crm_perror(LOG_ERR, "Stopping %s: Could not send -%d to process %d failed",
                   child->name, signal, child->pid);
    }

    return TRUE;
}
Example #11
0
static gboolean try_heartbeat(int command)
{
    crm_debug("Attempting to process %c command", command);
    
    if(command == 'i') {
	if(read_local_hb_uuid()) {
	    exit(0);
	}
	
    } else if(ccm_age_connect(&ccm_fd)) {
	int rc = 0;
	fd_set rset;	
	while (1) {
	    
	    sleep(1);
	    FD_ZERO(&rset);
	    FD_SET(ccm_fd, &rset);
	    
	    errno = 0;
	    rc = select(ccm_fd + 1, &rset, NULL,NULL,NULL);
	    
	    if(rc > 0 && oc_ev_handle_event(ccm_token) != 0) {
		crm_err("oc_ev_handle_event failed");
		exit(1);
		
	    } else if(rc < 0 && errno != EINTR) {
		crm_perror(LOG_ERR, "select failed");
		exit(1);
	    }
	    
	}
    }
    return FALSE;
}
Example #12
0
mainloop_io_t *
mainloop_add_ipc_client(const char *name, int priority, size_t max_size, void *userdata,
                        struct ipc_client_callbacks *callbacks)
{
    mainloop_io_t *client = NULL;
    crm_ipc_t *conn = crm_ipc_new(name, max_size);

    if (conn && crm_ipc_connect(conn)) {
        int32_t fd = crm_ipc_get_fd(conn);

        client = mainloop_add_fd(name, priority, fd, userdata, NULL);
    }

    if (client == NULL) {
        crm_perror(LOG_TRACE, "Connection to %s failed", name);
        if (conn) {
            crm_ipc_close(conn);
            crm_ipc_destroy(conn);
        }
        return NULL;
    }

    client->ipc = conn;
    client->destroy_fn = callbacks->destroy;
    client->dispatch_fn_ipc = callbacks->dispatch;
    return client;
}
Example #13
0
/*!
 * \internal
 * \brief Handle cluster communication related to pacemaker_remote node leaving
 *
 * \param[in] node_name  Name of lost node
 */
static void
remote_node_down(const char *node_name)
{
    xmlNode *update;
    int call_id = 0;
    int call_opt = crmd_cib_smart_opt();
    crm_node_t *node;

    /* Purge node from attrd's memory */
    update_attrd_remote_node_removed(node_name, NULL);

    /* Purge node's operation history and transient attributes from CIB */
    erase_status_tag(node_name, XML_CIB_TAG_LRM, call_opt);
    erase_status_tag(node_name, XML_TAG_TRANSIENT_NODEATTRS, call_opt);

    /* Ensure node is in the remote peer cache with lost state */
    node = crm_remote_peer_get(node_name);
    CRM_CHECK(node != NULL, return);
    crm_update_peer_state(__FUNCTION__, node, CRM_NODE_LOST, 0);

    /* Notify DC */
    send_remote_state_message(node_name, FALSE);

    /* Update CIB node state */
    update = create_xml_node(NULL, XML_CIB_TAG_STATUS);
    do_update_node_cib(node, node_update_cluster, update, __FUNCTION__);
    fsa_cib_update(XML_CIB_TAG_STATUS, update, call_opt, call_id, NULL);
    if (call_id < 0) {
        crm_perror(LOG_ERR, "%s CIB node state update", node_name);
    }
    free_xml(update);
}
Example #14
0
static int
crm_lock_pidfile(const char *filename, const char *name)
{
    long mypid = 0;
    int fd = 0, rc = 0;
    char buf[LOCKSTRLEN + 1];

    mypid = (unsigned long)getpid();

    rc = crm_pidfile_inuse(filename, 0, name);
    if (rc == -ENOENT) {
        /* exists but the process is not active */

    } else if (rc != pcmk_ok) {
        /* locked by existing process - give up */
        return rc;
    }

    if ((fd = open(filename, O_CREAT | O_WRONLY | O_EXCL, 0644)) < 0) {
        /* Hmmh, why did we fail? Anyway, nothing we can do about it */
        return -errno;
    }

    snprintf(buf, sizeof(buf), "%*lu\n", LOCKSTRLEN - 1, mypid);
    rc = write(fd, buf, LOCKSTRLEN);
    close(fd);

    if (rc != LOCKSTRLEN) {
        crm_perror(LOG_ERR, "Incomplete write to %s", filename);
        return -errno;
    }

    return crm_pidfile_inuse(filename, mypid, name);
}
Example #15
0
/*!
 * \internal
 * \brief Handle cluster communication related to pacemaker_remote node leaving
 *
 * \param[in] node_name  Name of lost node
 */
static void
remote_node_down(const char *node_name)
{
    xmlNode *update;
    int call_id = 0;
    int call_opt = crmd_cib_smart_opt();
    crm_node_t *node;

    /* Clear all node attributes */
    update_attrd_remote_node_removed(node_name, NULL);

    /* Ensure node is in the remote peer cache with lost state */
    node = crm_remote_peer_get(node_name);
    CRM_CHECK(node != NULL, return);
    crm_update_peer_state(__FUNCTION__, node, CRM_NODE_LOST, 0);

    /* Notify DC */
    send_remote_state_message(node_name, FALSE);

    /* Update CIB node state */
    update = create_xml_node(NULL, XML_CIB_TAG_STATUS);
    do_update_node_cib(node, node_update_cluster, update, __FUNCTION__);
    fsa_cib_update(XML_CIB_TAG_STATUS, update, call_opt, call_id, NULL);
    if (call_id < 0) {
        crm_perror(LOG_ERR, "%s CIB node state update", node_name);
    }
    free_xml(update);
}
Example #16
0
static void
set_ocf_env(const char *key, const char *value, gpointer user_data)
{
    if (setenv(key, value, 1) != 0) {
        crm_perror(LOG_ERR, "setenv failed for key:%s and value:%s", key, value);
    }
}
Example #17
0
char *
get_local_node_name(void)
{
    char *name = NULL;
    struct utsname res;

    if (use_cman) {
#if SUPPORT_CMAN
        cman_node_t us;
        cman_handle_t cman;

        cman = cman_init(NULL);
        if (cman != NULL && cman_is_active(cman)) {
            us.cn_name[0] = 0;
            cman_get_node(cman, CMAN_NODEID_US, &us);
            name = strdup(us.cn_name);
            crm_info("Using CMAN node name: %s", name);

        } else {
            crm_err("Couldn't determin node name from CMAN");
        }

        cman_finish(cman);
#endif

    } else if (uname(&res) < 0) {
        crm_perror(LOG_ERR, "Could not determin the current host");
        exit(100);

    } else {
        name = strdup(res.nodename);
    }
    return name;
}
static int
crm_uptime(struct timeval *output)
{
    static time_t expires = 0;
    static struct rusage info;

    time_t tm_now = time(NULL);

    if (expires < tm_now) {
        int rc = 0;

        info.ru_utime.tv_sec = 0;
        info.ru_utime.tv_usec = 0;
        rc = getrusage(RUSAGE_SELF, &info);

        output->tv_sec = 0;
        output->tv_usec = 0;

        if (rc < 0) {
            crm_perror(LOG_ERR, "Could not calculate the current uptime");
            expires = 0;
            return -1;
        }

        crm_debug("Current CPU usage is: %lds, %ldus", (long)info.ru_utime.tv_sec,
                  (long)info.ru_utime.tv_usec);
    }

    expires = tm_now + STORM_INTERVAL;  /* N seconds after the last _access_ */
    output->tv_sec = info.ru_utime.tv_sec;
    output->tv_usec = info.ru_utime.tv_usec;

    return 1;
}
Example #19
0
IPC_WaitConnection *
wait_channel_init(char daemonsocket[])
{
	IPC_WaitConnection *wait_ch;
	mode_t mask;
	char path[] = IPC_PATH_ATTR;
	GHashTable * attrs;

	
	attrs = g_hash_table_new(g_str_hash,g_str_equal);
	g_hash_table_insert(attrs, path, daemonsocket);
    
	mask = umask(0);
	wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs);
	if (wait_ch == NULL) {
		crm_perror(LOG_ERR,"Can't create wait channel of type %s",
			  IPC_ANYTYPE);
		exit(1);
	}
	mask = umask(mask);
    
	g_hash_table_destroy(attrs);
    
	return wait_ch;
}
Example #20
0
static gboolean
child_timeout_callback(gpointer p)
{
    mainloop_child_t *child = p;

    child->timerid = 0;
    if (child->timeout) {
        crm_crit("%s process (PID %d) will not die!", child->desc, (int)child->pid);
        return FALSE;
    }

    child->timeout = TRUE;
    crm_warn("%s process (PID %d) timed out", child->desc, (int)child->pid);

    if (kill(child->pid, SIGKILL) < 0) {
        if (errno == ESRCH) {
            /* Nothing left to do */
            return FALSE;
        }
        crm_perror(LOG_ERR, "kill(%d, KILL) failed", child->pid);
    }

    child->timerid = g_timeout_add(5000, child_timeout_callback, child);
    return FALSE;
}
Example #21
0
static void
sigchld_handler()
{
    if ((sigchld_pipe[1] >= 0) && (write(sigchld_pipe[1], "", 1) == -1)) {
        crm_perror(LOG_TRACE, "Could not poke SIGCHLD self-pipe");
    }
}
Example #22
0
gboolean
mainloop_add_signal(int sig, void (*dispatch) (int sig))
{
    GSource *source = NULL;
    int priority = G_PRIORITY_HIGH - 1;

    if (sig == SIGTERM) {
        /* TERM is higher priority than other signals,
         *   signals are higher priority than other ipc.
         * Yes, minus: smaller is "higher"
         */
        priority--;
    }

    if (sig >= NSIG || sig < 0) {
        crm_err("Signal %d is out of range", sig);
        return FALSE;

    } else if (crm_signals[sig] != NULL
               && crm_signals[sig]->handler == dispatch) {
        crm_trace("Signal handler for %d is already installed", sig);
        return TRUE;

    } else if (crm_signals[sig] != NULL) {
        crm_err("Different signal handler for %d is already installed", sig);
        return FALSE;
    }

    CRM_ASSERT(sizeof(crm_signal_t) > sizeof(GSource));
    source = g_source_new(&crm_signal_funcs, sizeof(crm_signal_t));

    crm_signals[sig] = (crm_signal_t *) mainloop_setup_trigger(source, priority, NULL, NULL);
    CRM_ASSERT(crm_signals[sig] != NULL);

    crm_signals[sig]->handler = dispatch;
    crm_signals[sig]->signal = sig;

    if (crm_signal(sig, mainloop_signal_handler) == FALSE) {
        crm_signal_t *tmp = crm_signals[sig];

        crm_signals[sig] = NULL;

        mainloop_destroy_trigger((crm_trigger_t *) tmp);
        return FALSE;
    }
#if 0
    /* If we want signals to interrupt mainloop's poll(), instead of waiting for
     * the timeout, then we should call siginterrupt() below
     *
     * For now, just enforce a low timeout
     */
    if (siginterrupt(sig, 1) < 0) {
        crm_perror(LOG_INFO, "Could not enable system call interruptions for signal %d", sig);
    }
#endif

    return TRUE;
}
Example #23
0
static gboolean
validate_cib_digest(xmlNode * local_cib, const char *sigfile)
{
    char *digest = NULL;
    char *expected = NULL;
    gboolean passed = FALSE;
    FILE *expected_strm = NULL;
    int start = 0, length = 0, read_len = 0;

    CRM_ASSERT(sigfile != NULL);

    expected_strm = fopen(sigfile, "r");
    if (expected_strm == NULL && errno == ENOENT) {
        crm_warn("No on-disk digest present");
        return TRUE;

    } else if (expected_strm == NULL) {
        crm_perror(LOG_ERR, "Could not open signature file %s for reading", sigfile);
        goto bail;
    }

    if (local_cib != NULL) {
        digest = calculate_on_disk_digest(local_cib);
    }

    start = ftell(expected_strm);
    fseek(expected_strm, 0L, SEEK_END);
    length = ftell(expected_strm);
    fseek(expected_strm, 0L, start);

    CRM_ASSERT(length >= 0);
    CRM_ASSERT(start == ftell(expected_strm));

    if (length > 0) {
        crm_trace("Reading %d bytes from file", length);
        expected = calloc(1, (length + 1));
        read_len = fread(expected, 1, length, expected_strm);   /* Coverity: False positive */
        CRM_ASSERT(read_len == length);
    }
    fclose(expected_strm);

  bail:
    if (expected == NULL) {
        crm_err("On-disk digest is empty");

    } else if (safe_str_eq(expected, digest)) {
        crm_trace("Digest comparision passed: %s", digest);
        passed = TRUE;

    } else {
        crm_err("Digest comparision failed: expected %s (%s), calculated %s",
                expected, sigfile, digest);
    }

    free(digest);
    free(expected);
    return passed;
}
Example #24
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);
    }
}
Example #25
0
/*!
 * \internal
 * \brief Handle cluster communication related to pacemaker_remote node joining
 *
 * \param[in] node_name  Name of newly integrated pacemaker_remote node
 */
static void
remote_node_up(const char *node_name)
{
    int call_opt, call_id = 0;
    xmlNode *update, *state;
    crm_node_t *node;

    CRM_CHECK(node_name != NULL, return);
    crm_info("Announcing pacemaker_remote node %s", node_name);

    /* Clear node's operation history. The node's transient attributes should
     * and normally will be cleared when the node leaves, but since remote node
     * state has a number of corner cases, clear them here as well, to be sure.
     */
    call_opt = crmd_cib_smart_opt();
    erase_status_tag(node_name, XML_CIB_TAG_LRM, call_opt);
    erase_status_tag(node_name, XML_TAG_TRANSIENT_NODEATTRS, call_opt);

    /* Clear node's probed attribute */
    update_attrd(node_name, CRM_OP_PROBED, NULL, NULL, TRUE);

    /* Ensure node is in the remote peer cache with member status */
    node = crm_remote_peer_get(node_name);
    CRM_CHECK(node != NULL, return);
    crm_update_peer_state(__FUNCTION__, node, CRM_NODE_MEMBER, 0);

    /* pacemaker_remote nodes don't participate in the membership layer,
     * so cluster nodes don't automatically get notified when they come and go.
     * We send a cluster message to the DC, and update the CIB node state entry,
     * so the DC will get it sooner (via message) or later (via CIB refresh),
     * and any other interested parties can query the CIB.
     */
    send_remote_state_message(node_name, TRUE);

    update = create_xml_node(NULL, XML_CIB_TAG_STATUS);
    state = create_node_state_update(node, node_update_cluster, update,
                                     __FUNCTION__);

    /* Clear the XML_NODE_IS_FENCED flag in the node state. If the node ever
     * needs to be fenced, this flag will allow various actions to determine
     * whether the fencing has happened yet.
     */
    crm_xml_add(state, XML_NODE_IS_FENCED, "0");

    /* TODO: If the remote connection drops, and this (async) CIB update either
     * failed or has not yet completed, later actions could mistakenly think the
     * node has already been fenced (if the XML_NODE_IS_FENCED attribute was
     * previously set, because it won't have been cleared). This could prevent
     * actual fencing or allow recurring monitor failures to be cleared too
     * soon. Ideally, we wouldn't rely on the CIB for the fenced status.
     */
    fsa_cib_update(XML_CIB_TAG_STATUS, update, call_opt, call_id, NULL);
    if (call_id < 0) {
        crm_perror(LOG_WARNING, "%s CIB node state setup", node_name);
    }
    free_xml(update);
}
Example #26
0
int
stonith__lha_validate(stonith_t *st, int call_options, const char *target,
                      const char *agent, GHashTable *params, int timeout,
                      char **output, char **error_output)
{
    errno = EOPNOTSUPP;
    crm_perror(LOG_ERR, "Cannot validate Linux-HA fence agents");
    return -EOPNOTSUPP;
}
Example #27
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;
}
Example #28
0
gboolean
systemd_unit_exec_with_unit(svc_action_t * op, const char *unit)
{
    const char *method = op->action;
    DBusMessage *msg = NULL;
    DBusMessage *reply = NULL;

    CRM_ASSERT(unit);

    if (safe_str_eq(op->action, "monitor") || safe_str_eq(method, "status")) {
        DBusPendingCall *pending = NULL;
        char *state;

        state = pcmk_dbus_get_property(systemd_proxy, BUS_NAME, unit,
                                       BUS_NAME ".Unit", "ActiveState",
                                       op->synchronous?NULL:systemd_unit_check,
                                       op, op->synchronous?NULL:&pending, op->timeout);
        if (op->synchronous) {
            systemd_unit_check("ActiveState", state, op);
            free(state);
            return op->rc == PCMK_OCF_OK;
        } else if (pending) {
            services_set_op_pending(op, pending);
            return TRUE;

        } else {
            return operation_finalize(op);
        }

    } else if (g_strcmp0(method, "start") == 0) {
        FILE *file_strm = NULL;
        char *override_dir = crm_strdup_printf("%s/%s.service.d", SYSTEMD_OVERRIDE_ROOT, op->agent);
        char *override_file = crm_strdup_printf("%s/%s.service.d/50-pacemaker.conf", SYSTEMD_OVERRIDE_ROOT, op->agent);

        method = "StartUnit";
        crm_build_path(override_dir, 0755);

        file_strm = fopen(override_file, "w");
        if (file_strm != NULL) {
            /* TODO: Insert the start timeout in too */
            char *override = crm_strdup_printf(
                "[Unit]\n"
                "Description=Cluster Controlled %s\n"
                "Before=pacemaker.service\n"
                "\n"
                "[Service]\n"
                "Restart=no\n",
                op->agent);

            int rc = fprintf(file_strm, "%s\n", override);

            free(override);
            if (rc < 0) {
                crm_perror(LOG_ERR, "Cannot write to systemd override file %s", override_file);
            }

        } else {
Example #29
0
/* terrible function name */
static int
child_kill_helper(mainloop_child_t *child)
{
    if (kill(-child->pid, SIGKILL) < 0) {
        crm_perror(LOG_ERR, "kill(%d, KILL) failed", child->pid);
        return -errno;
    }
    return 0;
}
Example #30
0
static gboolean
child_waitpid(mainloop_child_t *child, int flags)
{
    int rc = 0;
    int core = 0;
    int signo = 0;
    int status = 0;
    int exitcode = 0;

    rc = waitpid(child->pid, &status, flags);
    if(rc == 0) {
        crm_perror(LOG_DEBUG, "wait(%d) = %d", child->pid, rc);
        return FALSE;

    } else if(rc != child->pid) {
        signo = SIGCHLD;
        exitcode = 1;
        status = 1;
        crm_perror(LOG_ERR, "Call to waitpid(%d) failed", child->pid);

    } else {
        crm_trace("Managed process %d exited: %p", child->pid, child);

        if (WIFEXITED(status)) {
            exitcode = WEXITSTATUS(status);
            crm_trace("Managed process %d (%s) exited with rc=%d", child->pid, child->desc, exitcode);

        } else if (WIFSIGNALED(status)) {
            signo = WTERMSIG(status);
            crm_trace("Managed process %d (%s) exited with signal=%d", child->pid, child->desc, signo);
        }
#ifdef WCOREDUMP
        if (WCOREDUMP(status)) {
            core = 1;
            crm_err("Managed process %d (%s) dumped core", child->pid, child->desc);
        }
#endif
    }

    if (child->callback) {
        child->callback(child, child->pid, core, signo, exitcode);
    }
    return TRUE;
}