21 #include <sys/types.h> 
   28 #include <sys/types.h> 
   30 #include <sys/resource.h> 
   47     qb_log_from_external_source(__func__, __FILE__,
 
   48                                 "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s",
 
   79 ais_string_to_boolean(
const char *s)
 
   87     if (strcasecmp(s, 
"true") == 0
 
   88         || strcasecmp(s, 
"on") == 0
 
   89         || strcasecmp(s, 
"yes") == 0 || strcasecmp(s, 
"y") == 0 || strcasecmp(s, 
"1") == 0) {
 
   95 static char *opts_default[] = { NULL, NULL };
 
   96 static char *opts_vgrind[] = { NULL, NULL, NULL, NULL, NULL };
 
  101 #if defined(HAVE_SCHED_SETSCHEDULER) 
  102     int policy = sched_getscheduler(0);
 
  105         ais_perror(
"Could not get scheduling policy for %s", child->
name);
 
  110         if (policy != SCHED_OTHER) {
 
  111             struct sched_param sp;
 
  113             policy = SCHED_OTHER;
 
  114 #  if defined(SCHED_RESET_ON_FORK) 
  115             policy |= SCHED_RESET_ON_FORK;
 
  117             memset(&sp, 0, 
sizeof(sp));
 
  118             sp.sched_priority = 0;
 
  120             if (sched_setscheduler(0, policy, &sp) == -1) {
 
  121                 ais_perror(
"Could not reset scheduling policy to SCHED_OTHER for %s", child->
name);
 
  126         if (setpriority(PRIO_PROCESS, 0, priority) == -1) {
 
  127             ais_perror(
"Could not reset process priority to %d for %s", priority, child->
name);
 
  131     ais_info(
"The platform is missing process priority setting features. Leaving at default.");
 
  141     struct rlimit oflimits;
 
  142     gboolean use_valgrind = FALSE;
 
  143     gboolean use_callgrind = FALSE;
 
  144     const char *devnull = 
"/dev/null";
 
  145     const char *env_valgrind = getenv(
"PCMK_valgrind_enabled");
 
  146     const char *env_callgrind = getenv(
"PCMK_callgrind_enabled");
 
  149         ais_info(
"Nothing to do for child \"%s\"", child->
name);
 
  153     if (ais_string_to_boolean(env_callgrind)) {
 
  154         use_callgrind = TRUE;
 
  157     } 
else if (env_callgrind != NULL && strstr(env_callgrind, child->
name)) {
 
  158         use_callgrind = TRUE;
 
  161     } 
else if (ais_string_to_boolean(env_valgrind)) {
 
  164     } 
else if (env_valgrind != NULL && strstr(env_valgrind, child->
name)) {
 
  169         ais_warn(
"Cannot enable valgrind for %s:" 
  170                  " The location of the valgrind binary is unknown", child->
name);
 
  171         use_valgrind = FALSE;
 
  176             ais_err(
"Invalid uid (%s) specified for %s", child->
uid, child->
name);
 
  179         ais_info(
"Using uid=%u and group=%u for process %s", uid, gid, child->
name);
 
  185     if (child->
pid > 0) {
 
  188                  use_valgrind ? 
" (valgrind enabled: " VALGRIND_BIN ")" : 
"");
 
  191         pcmk_setscheduler(child);
 
  196             opts_vgrind[1] = ais_strdup(
"--tool=callgrind");
 
  197             opts_vgrind[2] = ais_strdup(
"--callgrind-out-file=" CRM_STATE_DIR "/callgrind.out.%p");
 
  198             opts_vgrind[3] = ais_strdup(child->
command);
 
  199             opts_vgrind[4] = NULL;
 
  201             opts_vgrind[1] = ais_strdup(child->
command);
 
  202             opts_vgrind[2] = NULL;
 
  203             opts_vgrind[3] = NULL;
 
  204             opts_vgrind[4] = NULL;
 
  206         opts_default[0] = ais_strdup(child->
command);
 
  208         if (uid && initgroups(child->
uid, gid) < 0) {
 
  212         if (uid && setuid(uid) < 0) {
 
  213             ais_perror(
"Could not set user to %d (%s)", uid, child->
uid);
 
  217         getrlimit(RLIMIT_NOFILE, &oflimits);
 
  218         for (; lpc < oflimits.rlim_cur; lpc++) {
 
  222         (void)open(devnull, O_RDONLY);  
 
  223         (void)open(devnull, O_WRONLY);  
 
  224         (void)open(devnull, O_WRONLY);  
 
  227     setenv(
"HA_COMPRESSION",    
"bz2",             1);
 
  228     setenv(
"HA_cluster_type",   
"openais",     1);
 
  243             (void)execvp(child->
command, opts_default);
 
  259         ais_info(
"Nothing to do for child \"%s\"", child->
name);
 
  265     if (child->
pid <= 0) {
 
  271     if (kill(child->
pid, signal) == 0) {
 
  286     ais_info(
"Destroying entry for node %u", node->
id);
 
  305         ais_info(
"Creating entry for node %u born on " U64T "", 
id, seq);
 
  308         node->
state = ais_strdup(
"unknown");
 
  319     if (born != 0 && node->
born != born) {
 
  322         ais_info(
"%p Node %u (%s) born on: " U64T, node, 
id, uname, born);
 
  325     if (version != NULL) {
 
  327         node->
version = ais_strdup(version);
 
  331         if (node->
uname == NULL || ais_str_eq(node->
uname, uname) == FALSE) {
 
  332             ais_info(
"%p Node %u now known as %s (was: %s)", node, 
id, uname, node->
uname);
 
  334             node->
uname = ais_strdup(uname);
 
  339     if (procs != 0 && procs != node->
processes) {
 
  340         ais_info(
"Node %s now has process list: %.32x (%u)", node->
uname, procs, procs);
 
  345     if (votes >= 0 && votes != node->
votes) {
 
  346         ais_info(
"Node %s now has %d quorum votes (was %d)", node->
uname, votes, node->
votes);
 
  352         if (node->
state == NULL || ais_str_eq(node->
state, state) == FALSE) {
 
  354             node->
state = ais_strdup(state);
 
  370     ais_err(
"Deleting by uname is not yet supported");
 
  381     if (node->
uname == NULL) {
 
  392     static int fixed_len = 4 + 8 + 7 + 6 + 6 + 7 + 11;
 
  402     size += strlen(node->
state);
 
  404         size += (7 + strlen(node->
uname));
 
  407         size += (6 + strlen(node->
addr));
 
  410         size += (9 + strlen(node->
version));
 
  412     data = realloc_safe(data, size);
 
  414     offset += snprintf(data + offset, size - offset, 
"<node id=\"%u\" ", node->
id);
 
  416         offset += snprintf(data + offset, size - offset, 
"uname=\"%s\" ", node->
uname);
 
  418     offset += snprintf(data + offset, size - offset, 
"state=\"%s\" ", node->
state);
 
  419     offset += snprintf(data + offset, size - offset, 
"born=\"" U64T "\" ", node->
born);
 
  420     offset += snprintf(data + offset, size - offset, 
"seen=\"" U64T "\" ", node->
last_seen);
 
  421     offset += snprintf(data + offset, size - offset, 
"votes=\"%d\" ", node->
votes);
 
  422     offset += snprintf(data + offset, size - offset, 
"processes=\"%u\" ", node->
processes);
 
  424         offset += snprintf(data + offset, size - offset, 
"addr=\"%s\" ", node->
addr);
 
  427         offset += snprintf(data + offset, size - offset, 
"version=\"%s\" ", node->
version);
 
  429     offset += snprintf(data + offset, size - offset, 
"/>");
 
  457     char *uncompressed = NULL;
 
  458     unsigned int new_size = msg->
size + 1;
 
  461         uncompressed = strdup(msg->
data);
 
  466         rc = BZ2_bzBuffToBuffDecompress(uncompressed, &new_size, (
char *)msg->
data,
 
  469             ais_info(
"rc=%d, new=%u expected=%u", rc, new_size, msg->
size);
 
  489         data_len = 1 + strlen(data);
 
  490         total_size += data_len;
 
  494     ais_msg->header.
size = total_size;
 
  495     ais_msg->header.error = CS_OK;
 
  496     ais_msg->header.
id = 0;
 
  498     ais_msg->
size = data_len;
 
  501         memcpy(ais_msg->
data, data, data_len);
 
  524 extern struct corosync_api_v1 *
pcmk_api;
 
  534     } 
else if (!libais_connection_active(conn)) {
 
  535         ais_warn(
"Connection no longer active");
 
  543         rc = pcmk_api->ipc_dispatch_send(conn, ais_msg, ais_msg->header.
size);
 
  557     static int msg_id = 0;
 
  565         data_len = 1 + strlen(data);
 
  567     total_size += data_len;
 
  571     ais_msg->
id = msg_id;
 
  572     ais_msg->header.
id = 
class;
 
  573     ais_msg->header.
size = total_size;
 
  574     ais_msg->header.error = CS_OK;
 
  576     ais_msg->
size = data_len;
 
  578         memcpy(ais_msg->
data, data, data_len);
 
  595         ais_warn(
"Sending message to %s failed: %d", msg_type2text(type), rc);
 
  604 ais_concat(
const char *prefix, 
const char *suffix, 
char join)
 
  607     char *new_str = NULL;
 
  611     len = strlen(prefix) + strlen(suffix) + 2;
 
  614     sprintf(new_str, 
"%s%c%s", prefix, join, suffix);
 
  615     new_str[len - 1] = 0;
 
  622     hdb_handle_t local_handle = 0;
 
  625     config->object_find_create(OBJECT_PARENT_HANDLE, name, strlen(name), &local_handle);
 
  626     ais_info(
"Local handle: %lld for %s", (
long long)local_handle, name);
 
  636     hdb_handle_t local_handle = 0;
 
  639     rc = config->object_find_next(top_handle, &local_handle);
 
  643         ais_info(
"No additional configuration supplied for: %s", name);
 
  646         ais_info(
"Processing additional %s options...", name);
 
  655     config->object_find_destroy(local_handle);
 
  661                hdb_handle_t object_service_handle, 
char *key, 
char **value, 
const char *fallback)
 
  663     char *env_key = NULL;
 
  667     if (object_service_handle > 0) {
 
  668         config->object_key_get(object_service_handle, key, strlen(key), (
void **)value, NULL);
 
  672         ais_info(
"Found '%s' for option: %s", *value, key);
 
  677     *value = getenv(env_key);
 
  681         ais_info(
"Found '%s' in ENV for option: %s", *value, key);
 
  686         ais_info(
"Defaulting to '%s' for option: %s", fallback, key);
 
  687         *value = ais_strdup(fallback);
 
  690         ais_info(
"No default for option: %s", key);
 
  702     } 
else if (strcasecmp(value, 
"true") == 0
 
  703                || strcasecmp(value, 
"on") == 0
 
  704                || strcasecmp(value, 
"yes") == 0
 
  705                || strcasecmp(value, 
"y") == 0 || strcasecmp(value, 
"1") == 0) {
 
  714     long long result = -1;
 
  715     char *local_end_text = NULL;
 
  721         if (end_text != NULL) {
 
  722             result = strtol(text, end_text, 10);
 
  724             result = strtol(text, &local_end_text, 10);
 
  727         if (end_text != NULL) {
 
  728             result = strtoll(text, end_text, 10);
 
  730             result = strtoll(text, &local_end_text, 10);
 
  734         if (errno == EINVAL) {
 
  735             ais_err(
"Conversion of %s failed", text);
 
  738         } 
else if (errno == ERANGE) {
 
  739             ais_err(
"Conversion of %s was clipped: %lld", text, result);
 
  741         } 
else if (errno != 0) {
 
  745         if (local_end_text != NULL && local_end_text[0] != 
'\0') {
 
  746             ais_err(
"Characters left over after parsing '%s': '%s'", text, local_end_text);
 
  752 #define PW_BUFFER_LEN 500 
  760     struct passwd *pwentry = NULL;
 
  767             *uid = pwentry->pw_uid;
 
  770             *gid = pwentry->pw_gid;
 
  772         ais_debug(
"Cluster user %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
 
  775         ais_err(
"Cluster user %s does not exist", name);
 
enum crm_ais_msg_types type
 
hdb_handle_t config_find_init(struct corosync_api_v1 *config, char *name)
 
int pcmk_user_lookup(const char *name, uid_t *uid, gid_t *gid)
 
long long ais_get_int(const char *text, char **end_text)
 
void log_ais_message(int level, const AIS_Message *msg)
 
#define ais_notice(fmt, args...)
 
void config_find_done(struct corosync_api_v1 *config, hdb_handle_t local_handle)
 
#define ais_perror(fmt, args...)
 
#define ais_info(fmt, args...)
 
#define ais_trace(fmt, args...)
 
#define ais_malloc0(malloc_obj, length)
 
struct pcmk_env_s pcmk_env
 
int ais_get_boolean(const char *value)
 
int update_member(unsigned int id, uint64_t born, uint64_t seq, int32_t votes, uint32_t procs, const char *uname, const char *state, const char *version)
 
struct corosync_api_v1 * pcmk_api
 
#define ais_err(fmt, args...)
 
int get_config_opt(struct corosync_api_v1 *config, hdb_handle_t object_service_handle, char *key, char **value, const char *fallback)
 
int setenv(const char *name, const char *value, int why)
 
int send_plugin_msg(enum crm_ais_msg_types type, const char *host, const char *data)
 
gboolean stop_child(crm_child_t *child, int signal)
 
const char * member_uname(uint32_t id)
 
struct crm_ais_msg_s AIS_Message
 
#define ais_data_len(msg)
 
#define ais_debug(fmt, args...)
 
char * ais_concat(const char *prefix, const char *suffix, char join)
 
void swap_sender(AIS_Message *msg)
 
hdb_handle_t config_find_next(struct corosync_api_v1 *config, char *name, hdb_handle_t top_handle)
 
void destroy_ais_node(gpointer data)
 
int send_plugin_msg_raw(const AIS_Message *ais_msg)
 
char * get_ais_data(const AIS_Message *msg)
 
#define ais_warn(fmt, args...)
 
gboolean spawn_child(crm_child_t *child)
 
char * append_member(char *data, crm_node_t *node)
 
void delete_member(uint32_t id, const char *uname)
 
int send_client_msg(void *conn, enum crm_ais_msg_class class, enum crm_ais_msg_types type, const char *data)
 
int send_client_ipc(void *conn, const AIS_Message *ais_msg)
 
GHashTable * membership_list
 
enum crm_ais_msg_types type