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