Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/lib/ais/utils.c b/lib/ais/utils.c
index 37f2e7ede5..e56fb6d0ca 100644
--- a/lib/ais/utils.c
+++ b/lib/ais/utils.c
@@ -1,780 +1,780 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <crm_internal.h>
#include <crm/cluster/internal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <pwd.h>
#include <glib.h>
#include <bzlib.h>
#include <grp.h>
#include "./utils.h"
#include "./plugin.h"
struct pcmk_env_s pcmk_env;
void
log_ais_message(int level, const AIS_Message * msg)
{
char *data = get_ais_data(msg);
qb_log_from_external_source(__func__, __FILE__,
"Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s",
level, __LINE__, 0,
msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type),
ais_dest(&(msg->sender)), msg_type2text(msg->sender.type),
msg->sender.pid,
msg->sender.uname == local_uname ? "false" : "true",
ais_data_len(msg), data);
/* do_ais_log(level, */
/* "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s", */
/* msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type), */
/* ais_dest(&(msg->sender)), msg_type2text(msg->sender.type), */
/* msg->sender.pid, */
/* msg->sender.uname==local_uname?"false":"true", */
/* ais_data_len(msg), data); */
ais_free(data);
}
/*
static gboolean ghash_find_by_uname(gpointer key, gpointer value, gpointer user_data)
{
crm_node_t *node = value;
int id = GPOINTER_TO_INT(user_data);
if (node->id == id) {
return TRUE;
}
return FALSE;
}
*/
static int
ais_string_to_boolean(const char *s)
{
int rc = 0;
if (s == NULL) {
return rc;
}
if (strcasecmp(s, "true") == 0
|| strcasecmp(s, "on") == 0
|| strcasecmp(s, "yes") == 0 || strcasecmp(s, "y") == 0 || strcasecmp(s, "1") == 0) {
rc = 1;
}
return rc;
}
static char *opts_default[] = { NULL, NULL };
static char *opts_vgrind[] = { NULL, NULL, NULL, NULL, NULL };
static void
pcmk_setscheduler(crm_child_t * child)
{
#if defined(HAVE_SCHED_SETSCHEDULER)
int policy = sched_getscheduler(0);
if (policy == -1) {
ais_perror("Could not get scheduling policy for %s", child->name);
} else {
int priority = -10;
if (policy != SCHED_OTHER) {
struct sched_param sp;
policy = SCHED_OTHER;
# if defined(SCHED_RESET_ON_FORK)
policy |= SCHED_RESET_ON_FORK;
# endif
memset(&sp, 0, sizeof(sp));
sp.sched_priority = 0;
if (sched_setscheduler(0, policy, &sp) == -1) {
ais_perror("Could not reset scheduling policy to SCHED_OTHER for %s", child->name);
return;
}
}
if (setpriority(PRIO_PROCESS, 0, priority) == -1) {
ais_perror("Could not reset process priority to %d for %s", priority, child->name);
}
}
#else
ais_info("The platform is missing process priority setting features. Leaving at default.");
#endif
}
gboolean
spawn_child(crm_child_t * child)
{
int lpc = 0;
uid_t uid = 0;
gid_t gid = 0;
struct rlimit oflimits;
gboolean use_valgrind = FALSE;
gboolean use_callgrind = FALSE;
const char *devnull = "/dev/null";
const char *env_valgrind = getenv("PCMK_valgrind_enabled");
const char *env_callgrind = getenv("PCMK_callgrind_enabled");
if (child->command == NULL) {
ais_info("Nothing to do for child \"%s\"", child->name);
return TRUE;
}
if (ais_string_to_boolean(env_callgrind)) {
use_callgrind = TRUE;
use_valgrind = TRUE;
} else if (env_callgrind != NULL && strstr(env_callgrind, child->name)) {
use_callgrind = TRUE;
use_valgrind = TRUE;
} else if (ais_string_to_boolean(env_valgrind)) {
use_valgrind = TRUE;
} else if (env_valgrind != NULL && strstr(env_valgrind, child->name)) {
use_valgrind = TRUE;
}
if (use_valgrind && strlen(VALGRIND_BIN) == 0) {
ais_warn("Cannot enable valgrind for %s:"
" The location of the valgrind binary is unknown", child->name);
use_valgrind = FALSE;
}
if (child->uid) {
if (pcmk_user_lookup(child->uid, &uid, &gid) < 0) {
ais_err("Invalid uid (%s) specified for %s", child->uid, child->name);
return FALSE;
}
ais_info("Using uid=%u and group=%u for process %s", uid, gid, child->name);
}
child->pid = fork();
AIS_ASSERT(child->pid != -1);
if (child->pid > 0) {
/* parent */
ais_info("Forked child %d for process %s%s", child->pid, child->name,
use_valgrind ? " (valgrind enabled: " VALGRIND_BIN ")" : "");
} else {
pcmk_setscheduler(child);
/* Setup the two alternate arg arrarys */
opts_vgrind[0] = ais_strdup(VALGRIND_BIN);
if (use_callgrind) {
opts_vgrind[1] = ais_strdup("--tool=callgrind");
opts_vgrind[2] = ais_strdup("--callgrind-out-file=" CRM_STATE_DIR "/callgrind.out.%p");
opts_vgrind[3] = ais_strdup(child->command);
opts_vgrind[4] = NULL;
} else {
opts_vgrind[1] = ais_strdup(child->command);
opts_vgrind[2] = NULL;
opts_vgrind[3] = NULL;
opts_vgrind[4] = NULL;
}
opts_default[0] = ais_strdup(child->command);;
if (uid && initgroups(child->uid, gid) < 0) {
ais_perror("Cannot initalize groups for %s", child->uid);
}
if (uid && setuid(uid) < 0) {
ais_perror("Could not set user to %d (%s)", uid, child->uid);
}
/* Close all open file descriptors */
getrlimit(RLIMIT_NOFILE, &oflimits);
for (; lpc < oflimits.rlim_cur; lpc++) {
close(lpc);
}
(void)open(devnull, O_RDONLY); /* Stdin: fd 0 */
(void)open(devnull, O_WRONLY); /* Stdout: fd 1 */
(void)open(devnull, O_WRONLY); /* Stderr: fd 2 */
/* *INDENT-OFF* */
setenv("HA_COMPRESSION", "bz2", 1);
setenv("HA_cluster_type", "openais", 1);
setenv("HA_debug", pcmk_env.debug, 1);
setenv("HA_logfacility", pcmk_env.syslog, 1);
setenv("HA_LOGFACILITY", pcmk_env.syslog, 1);
setenv("HA_use_logd", pcmk_env.use_logd, 1);
setenv("HA_quorum_type", pcmk_env.quorum, 1);
/* *INDENT-ON* */
if (pcmk_env.logfile) {
- setenv("HA_debugfile", pcmk_env.logfile, 1);
+ setenv("HA_logfile", pcmk_env.logfile, 1);
}
if (use_valgrind) {
(void)execvp(VALGRIND_BIN, opts_vgrind);
} else {
(void)execvp(child->command, opts_default);
}
ais_perror("FATAL: Cannot exec %s", child->command);
exit(100);
}
return TRUE;
}
gboolean
stop_child(crm_child_t * child, int signal)
{
if (signal == 0) {
signal = SIGTERM;
}
if (child->command == NULL) {
ais_info("Nothing to do for child \"%s\"", child->name);
return TRUE;
}
ais_debug("Stopping CRM child \"%s\"", child->name);
if (child->pid <= 0) {
ais_trace("Client %s not running", child->name);
return TRUE;
}
errno = 0;
if (kill(child->pid, signal) == 0) {
ais_notice("Sent -%d to %s: [%d]", signal, child->name, child->pid);
} else {
ais_perror("Sent -%d to %s: [%d]", signal, child->name, child->pid);
}
return TRUE;
}
void
destroy_ais_node(gpointer data)
{
crm_node_t *node = data;
ais_info("Destroying entry for node %u", node->id);
ais_free(node->addr);
ais_free(node->uname);
ais_free(node->state);
ais_free(node);
}
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)
{
int changed = 0;
crm_node_t *node = NULL;
node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id));
if (node == NULL) {
ais_malloc0(node, sizeof(crm_node_t));
ais_info("Creating entry for node %u born on " U64T "", id, seq);
node->id = id;
node->addr = NULL;
node->state = ais_strdup("unknown");
g_hash_table_insert(membership_list, GUINT_TO_POINTER(id), node);
node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id));
}
AIS_ASSERT(node != NULL);
if (seq != 0) {
node->last_seen = seq;
}
if (born != 0 && node->born != born) {
changed = TRUE;
node->born = born;
ais_info("%p Node %u (%s) born on: " U64T, node, id, uname, born);
}
if (version != NULL) {
ais_free(node->version);
node->version = ais_strdup(version);
}
if (uname != NULL) {
if (node->uname == NULL || ais_str_eq(node->uname, uname) == FALSE) {
ais_info("%p Node %u now known as %s (was: %s)", node, id, uname, node->uname);
ais_free(node->uname);
node->uname = ais_strdup(uname);
changed = TRUE;
}
}
if (procs != 0 && procs != node->processes) {
ais_info("Node %s now has process list: %.32x (%u)", node->uname, procs, procs);
node->processes = procs;
changed = TRUE;
}
if (votes >= 0 && votes != node->votes) {
ais_info("Node %s now has %d quorum votes (was %d)", node->uname, votes, node->votes);
node->votes = votes;
changed = TRUE;
}
if (state != NULL) {
if (node->state == NULL || ais_str_eq(node->state, state) == FALSE) {
ais_free(node->state);
node->state = ais_strdup(state);
ais_info("Node %u/%s is now: %s", id, node->uname ? node->uname : "unknown", state);
changed = TRUE;
}
}
return changed;
}
void
delete_member(uint32_t id, const char *uname)
{
if (uname == NULL) {
g_hash_table_remove(membership_list, GUINT_TO_POINTER(id));
return;
}
ais_err("Deleting by uname is not yet supported");
}
const char *
member_uname(uint32_t id)
{
crm_node_t *node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id));
if (node == NULL) {
return ".unknown.";
}
if (node->uname == NULL) {
return ".pending.";
}
return node->uname;
}
char *
append_member(char *data, crm_node_t * node)
{
int size = 1; /* nul */
int offset = 0;
static int fixed_len = 4 + 8 + 7 + 6 + 6 + 7 + 11;
if (data) {
size = strlen(data);
}
offset = size;
size += fixed_len;
size += 32; /* node->id */
size += 100; /* node->seq, node->born */
size += strlen(node->state);
if (node->uname) {
size += (7 + strlen(node->uname));
}
if (node->addr) {
size += (6 + strlen(node->addr));
}
if (node->version) {
size += (9 + strlen(node->version));
}
data = realloc(data, size);
offset += snprintf(data + offset, size - offset, "<node id=\"%u\" ", node->id);
if (node->uname) {
offset += snprintf(data + offset, size - offset, "uname=\"%s\" ", node->uname);
}
offset += snprintf(data + offset, size - offset, "state=\"%s\" ", node->state);
offset += snprintf(data + offset, size - offset, "born=\"" U64T "\" ", node->born);
offset += snprintf(data + offset, size - offset, "seen=\"" U64T "\" ", node->last_seen);
offset += snprintf(data + offset, size - offset, "votes=\"%d\" ", node->votes);
offset += snprintf(data + offset, size - offset, "processes=\"%u\" ", node->processes);
if (node->addr) {
offset += snprintf(data + offset, size - offset, "addr=\"%s\" ", node->addr);
}
if (node->version) {
offset += snprintf(data + offset, size - offset, "version=\"%s\" ", node->version);
}
offset += snprintf(data + offset, size - offset, "/>");
return data;
}
void
swap_sender(AIS_Message * msg)
{
int tmp = 0;
char tmp_s[256];
tmp = msg->host.type;
msg->host.type = msg->sender.type;
msg->sender.type = tmp;
tmp = msg->host.type;
msg->host.size = msg->sender.type;
msg->sender.type = tmp;
memcpy(tmp_s, msg->host.uname, 256);
memcpy(msg->host.uname, msg->sender.uname, 256);
memcpy(msg->sender.uname, tmp_s, 256);
}
char *
get_ais_data(const AIS_Message * msg)
{
int rc = BZ_OK;
char *uncompressed = NULL;
unsigned int new_size = msg->size + 1;
if (msg->is_compressed == FALSE) {
uncompressed = strdup(msg->data);
} else {
ais_malloc0(uncompressed, new_size);
rc = BZ2_bzBuffToBuffDecompress(uncompressed, &new_size, (char *)msg->data,
msg->compressed_size, 1, 0);
if (rc != BZ_OK) {
ais_info("rc=%d, new=%u expected=%u", rc, new_size, msg->size);
}
AIS_ASSERT(rc == BZ_OK);
AIS_ASSERT(new_size == msg->size);
}
return uncompressed;
}
int
send_plugin_msg(enum crm_ais_msg_types type, const char *host, const char *data)
{
int rc = 0;
int data_len = 0;
AIS_Message *ais_msg = NULL;
int total_size = sizeof(AIS_Message);
AIS_ASSERT(local_nodeid != 0);
if (data != NULL) {
data_len = 1 + strlen(data);
total_size += data_len;
}
ais_malloc0(ais_msg, total_size);
ais_msg->header.size = total_size;
ais_msg->header.error = CS_OK;
ais_msg->header.id = 0;
ais_msg->size = data_len;
ais_msg->sender.type = crm_msg_ais;
if (data != NULL) {
memcpy(ais_msg->data, data, data_len);
}
ais_msg->host.type = type;
ais_msg->host.id = 0;
if (host) {
ais_msg->host.size = strlen(host);
memset(ais_msg->host.uname, 0, MAX_NAME);
memcpy(ais_msg->host.uname, host, ais_msg->host.size);
/* ais_msg->host.id = nodeid_lookup(host); */
} else {
ais_msg->host.type = type;
ais_msg->host.size = 0;
memset(ais_msg->host.uname, 0, MAX_NAME);
}
rc = send_plugin_msg_raw(ais_msg);
ais_free(ais_msg);
return rc;
}
extern struct corosync_api_v1 *pcmk_api;
int
send_client_ipc(void *conn, const AIS_Message * ais_msg)
{
int rc = -1;
if (conn == NULL) {
rc = -2;
} else if (!libais_connection_active(conn)) {
ais_warn("Connection no longer active");
rc = -3;
/* } else if ((queue->size - 1) == queue->used) { */
/* ais_err("Connection is throttled: %d", queue->size); */
} else {
#if SUPPORT_COROSYNC
rc = pcmk_api->ipc_dispatch_send(conn, ais_msg, ais_msg->header.size);
#endif
}
return rc;
}
int
send_client_msg(void *conn, enum crm_ais_msg_class class, enum crm_ais_msg_types type,
const char *data)
{
int rc = 0;
int data_len = 0;
int total_size = sizeof(AIS_Message);
AIS_Message *ais_msg = NULL;
static int msg_id = 0;
AIS_ASSERT(local_nodeid != 0);
msg_id++;
AIS_ASSERT(msg_id != 0 /* wrap-around */ );
if (data != NULL) {
data_len = 1 + strlen(data);
}
total_size += data_len;
ais_malloc0(ais_msg, total_size);
ais_msg->id = msg_id;
ais_msg->header.id = class;
ais_msg->header.size = total_size;
ais_msg->header.error = CS_OK;
ais_msg->size = data_len;
if (data != NULL) {
memcpy(ais_msg->data, data, data_len);
}
ais_msg->host.size = 0;
ais_msg->host.type = type;
memset(ais_msg->host.uname, 0, MAX_NAME);
ais_msg->host.id = 0;
ais_msg->sender.type = crm_msg_ais;
ais_msg->sender.size = local_uname_len;
memset(ais_msg->sender.uname, 0, MAX_NAME);
memcpy(ais_msg->sender.uname, local_uname, ais_msg->sender.size);
ais_msg->sender.id = local_nodeid;
rc = send_client_ipc(conn, ais_msg);
if (rc != 0) {
ais_warn("Sending message to %s failed: %d", msg_type2text(type), rc);
log_ais_message(LOG_DEBUG, ais_msg);
}
ais_free(ais_msg);
return rc;
}
char *
ais_concat(const char *prefix, const char *suffix, char join)
{
int len = 0;
char *new_str = NULL;
AIS_ASSERT(prefix != NULL);
AIS_ASSERT(suffix != NULL);
len = strlen(prefix) + strlen(suffix) + 2;
ais_malloc0(new_str, (len));
sprintf(new_str, "%s%c%s", prefix, join, suffix);
new_str[len - 1] = 0;
return new_str;
}
hdb_handle_t
config_find_init(struct corosync_api_v1 * config, char *name)
{
hdb_handle_t local_handle = 0;
#if SUPPORT_COROSYNC
config->object_find_create(OBJECT_PARENT_HANDLE, name, strlen(name), &local_handle);
ais_info("Local handle: %lld for %s", (long long)local_handle, name);
#endif
return local_handle;
}
hdb_handle_t
config_find_next(struct corosync_api_v1 * config, char *name, hdb_handle_t top_handle)
{
int rc = 0;
hdb_handle_t local_handle = 0;
#if SUPPORT_COROSYNC
rc = config->object_find_next(top_handle, &local_handle);
#endif
if (rc < 0) {
ais_info("No additional configuration supplied for: %s", name);
local_handle = 0;
} else {
ais_info("Processing additional %s options...", name);
}
return local_handle;
}
void
config_find_done(struct corosync_api_v1 *config, hdb_handle_t local_handle)
{
#if SUPPORT_COROSYNC
config->object_find_destroy(local_handle);
#endif
}
int
get_config_opt(struct corosync_api_v1 *config,
hdb_handle_t object_service_handle, char *key, char **value, const char *fallback)
{
char *env_key = NULL;
*value = NULL;
if (object_service_handle > 0) {
config->object_key_get(object_service_handle, key, strlen(key), (void **)value, NULL);
}
if (*value) {
ais_info("Found '%s' for option: %s", *value, key);
return 0;
}
env_key = ais_concat("HA", key, '_');
*value = getenv(env_key);
ais_free(env_key);
if (*value) {
ais_info("Found '%s' in ENV for option: %s", *value, key);
return 0;
}
if (fallback) {
ais_info("Defaulting to '%s' for option: %s", fallback, key);
*value = ais_strdup(fallback);
} else {
ais_info("No default for option: %s", key);
}
return -1;
}
int
ais_get_boolean(const char *value)
{
if (value == NULL) {
return 0;
} else if (strcasecmp(value, "true") == 0
|| strcasecmp(value, "on") == 0
|| strcasecmp(value, "yes") == 0
|| strcasecmp(value, "y") == 0 || strcasecmp(value, "1") == 0) {
return 1;
}
return 0;
}
long long
ais_get_int(const char *text, char **end_text)
{
long long result = -1;
char *local_end_text = NULL;
errno = 0;
if (text != NULL) {
#ifdef ANSI_ONLY
if (end_text != NULL) {
result = strtol(text, end_text, 10);
} else {
result = strtol(text, &local_end_text, 10);
}
#else
if (end_text != NULL) {
result = strtoll(text, end_text, 10);
} else {
result = strtoll(text, &local_end_text, 10);
}
#endif
if (errno == EINVAL) {
ais_err("Conversion of %s failed", text);
result = -1;
} else if (errno == ERANGE) {
ais_err("Conversion of %s was clipped: %lld", text, result);
} else if (errno != 0) {
ais_perror("Conversion of %s failed:", text);
}
if (local_end_text != NULL && local_end_text[0] != '\0') {
ais_err("Characters left over after parsing '%s': '%s'", text, local_end_text);
}
}
return result;
}
#define PW_BUFFER_LEN 500
int
pcmk_user_lookup(const char *name, uid_t * uid, gid_t * gid)
{
int rc = -1;
char *buffer = NULL;
struct passwd pwd;
struct passwd *pwentry = NULL;
ais_malloc0(buffer, PW_BUFFER_LEN);
getpwnam_r(name, &pwd, buffer, PW_BUFFER_LEN, &pwentry);
if (pwentry) {
rc = 0;
if (uid) {
*uid = pwentry->pw_uid;
}
if (gid) {
*gid = pwentry->pw_gid;
}
ais_debug("Cluster user %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
} else {
ais_err("Cluster user %s does not exist", name);
}
ais_free(buffer);
return rc;
}
diff --git a/lib/common/logging.c b/lib/common/logging.c
index e74ac83ca9..9131a1591e 100644
--- a/lib/common/logging.c
+++ b/lib/common/logging.c
@@ -1,1163 +1,1178 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <crm_internal.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <libgen.h>
#include <signal.h>
#include <bzlib.h>
#include <qb/qbdefs.h>
#include <crm/crm.h>
#include <crm/common/mainloop.h>
unsigned int crm_log_priority = LOG_NOTICE;
unsigned int crm_log_level = LOG_INFO;
static gboolean crm_tracing_enabled(void);
unsigned int crm_trace_nonlog = 0;
bool crm_is_daemon = 0;
#ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
GLogFunc glib_log_default;
static void
crm_glib_handler(const gchar * log_domain, GLogLevelFlags flags, const gchar * message,
gpointer user_data)
{
int log_level = LOG_WARNING;
GLogLevelFlags msg_level = (flags & G_LOG_LEVEL_MASK);
static struct qb_log_callsite *glib_cs = NULL;
if (glib_cs == NULL) {
glib_cs = qb_log_callsite_get(__FUNCTION__, __FILE__, "glib-handler", LOG_DEBUG, __LINE__, crm_trace_nonlog);
}
switch (msg_level) {
case G_LOG_LEVEL_CRITICAL:
log_level = LOG_CRIT;
if (crm_is_callsite_active(glib_cs, LOG_DEBUG, 0) == FALSE) {
/* log and record how we got here */
crm_abort(__FILE__, __FUNCTION__, __LINE__, message, TRUE, TRUE);
}
break;
case G_LOG_LEVEL_ERROR:
log_level = LOG_ERR;
break;
case G_LOG_LEVEL_MESSAGE:
log_level = LOG_NOTICE;
break;
case G_LOG_LEVEL_INFO:
log_level = LOG_INFO;
break;
case G_LOG_LEVEL_DEBUG:
log_level = LOG_DEBUG;
break;
case G_LOG_LEVEL_WARNING:
case G_LOG_FLAG_RECURSION:
case G_LOG_FLAG_FATAL:
case G_LOG_LEVEL_MASK:
log_level = LOG_WARNING;
break;
}
do_crm_log(log_level, "%s: %s", log_domain, message);
}
#endif
#ifndef NAME_MAX
# define NAME_MAX 256
#endif
static void
crm_trigger_blackbox(int nsig)
{
if(nsig == SIGTRAP) {
/* Turn it on if it wasn't already */
crm_enable_blackbox(nsig);
}
crm_write_blackbox(nsig, NULL);
}
const char *
daemon_option(const char *option)
{
char env_name[NAME_MAX];
const char *value = NULL;
snprintf(env_name, NAME_MAX, "PCMK_%s", option);
value = getenv(env_name);
if (value != NULL) {
crm_trace("Found %s = %s", env_name, value);
return value;
}
snprintf(env_name, NAME_MAX, "HA_%s", option);
value = getenv(env_name);
if (value != NULL) {
crm_trace("Found %s = %s", env_name, value);
return value;
}
crm_trace("Nothing found for %s", option);
return NULL;
}
void
set_daemon_option(const char *option, const char *value)
{
char env_name[NAME_MAX];
snprintf(env_name, NAME_MAX, "PCMK_%s", option);
if (value) {
crm_trace("Setting %s to %s", env_name, value);
setenv(env_name, value, 1);
} else {
crm_trace("Unsetting %s", env_name);
unsetenv(env_name);
}
snprintf(env_name, NAME_MAX, "HA_%s", option);
if (value) {
crm_trace("Setting %s to %s", env_name, value);
setenv(env_name, value, 1);
} else {
crm_trace("Unsetting %s", env_name);
unsetenv(env_name);
}
}
gboolean
daemon_option_enabled(const char *daemon, const char *option)
{
const char *value = daemon_option(option);
if (value != NULL && crm_is_true(value)) {
return TRUE;
} else if (value != NULL && strstr(value, daemon)) {
return TRUE;
}
return FALSE;
}
void
crm_log_deinit(void)
{
#ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
g_log_set_default_handler(glib_log_default, NULL);
#endif
}
#define FMT_MAX 256
static void
set_format_string(int method, const char *daemon)
{
int offset = 0;
char fmt[FMT_MAX];
if (method > QB_LOG_STDERR) {
/* When logging to a file */
struct utsname res;
if (uname(&res) == 0) {
offset +=
snprintf(fmt + offset, FMT_MAX - offset, "%%t [%d] %s %10s: ", getpid(),
res.nodename, daemon);
} else {
offset += snprintf(fmt + offset, FMT_MAX - offset, "%%t [%d] %10s: ", getpid(), daemon);
}
}
if (crm_tracing_enabled() && method >= QB_LOG_STDERR) {
offset += snprintf(fmt + offset, FMT_MAX - offset, "(%%-12f:%%5l %%g) %%-7p: %%n: ");
} else {
offset += snprintf(fmt + offset, FMT_MAX - offset, "%%g %%-7p: %%n: ");
}
if (method == QB_LOG_SYSLOG) {
offset += snprintf(fmt + offset, FMT_MAX - offset, "%%b");
} else {
offset += snprintf(fmt + offset, FMT_MAX - offset, "\t%%b");
}
qb_log_format_set(method, fmt);
}
gboolean
crm_add_logfile(const char *filename)
{
struct stat parent;
int fd = 0, rc = 0;
FILE *logfile = NULL;
char *parent_dir = NULL;
char *filename_cp;
static gboolean have_logfile = FALSE;
if (filename == NULL && have_logfile == FALSE) {
filename = "/var/log/pacemaker.log";
}
if (filename == NULL) {
return FALSE; /* Nothing to do */
+ } else if(safe_str_eq(filename, "none")) {
+ return FALSE; /* Nothing to do */
+ } else if(safe_str_eq(filename, "/dev/null")) {
+ return FALSE; /* Nothing to do */
}
/* Check the parent directory */
filename_cp = strdup(filename);
parent_dir = dirname(filename_cp);
rc = stat(parent_dir, &parent);
if (rc != 0) {
crm_err("Directory '%s' does not exist: logging to '%s' is disabled", parent_dir, filename);
free(filename_cp);
return FALSE;
}
free(filename_cp);
errno = 0;
logfile = fopen(filename, "a");
if(logfile == NULL) {
crm_err("%s (%d): Logging to '%s' as uid=%u, gid=%u is disabled",
pcmk_strerror(errno), errno, filename, geteuid(), getegid());
return FALSE;
}
/* Check/Set permissions if we're root */
if (geteuid() == 0) {
struct stat st;
uid_t pcmk_uid = 0;
gid_t pcmk_gid = 0;
gboolean fix = FALSE;
int logfd = fileno(logfile);
rc = fstat(logfd, &st);
if (rc < 0) {
crm_perror(LOG_WARNING, "Cannot stat %s", filename);
fclose(logfile);
return FALSE;
}
if(crm_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) == 0) {
if (st.st_gid != pcmk_gid) {
/* Wrong group */
fix = TRUE;
} else if ((st.st_mode & S_IRWXG) != (S_IRGRP | S_IWGRP)) {
/* Not read/writable by the correct group */
fix = TRUE;
}
}
if (fix) {
rc = fchown(logfd, pcmk_uid, pcmk_gid);
if (rc < 0) {
crm_warn("Cannot change the ownership of %s to user %s and gid %d",
filename, CRM_DAEMON_USER, pcmk_gid);
}
rc = fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (rc < 0) {
crm_warn("Cannot change the mode of %s to rw-rw----", filename);
}
fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n",
pcmk_uid, pcmk_gid, filename);
if (fflush(logfile) < 0 || fsync(logfd) < 0) {
crm_err("Couldn't write out logfile: %s", filename);
}
}
}
/* Close and reopen with libqb */
fclose(logfile);
fd = qb_log_file_open(filename);
if (fd < 0) {
crm_perror(LOG_WARNING, "Couldn't send additional logging to %s", filename);
return FALSE;
}
crm_notice("Additional logging available in %s", filename);
qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
/* qb_log_ctl(fd, QB_LOG_CONF_FILE_SYNC, 1); Turn on synchronous writes */
/* Enable callsites */
crm_update_callsites();
have_logfile = TRUE;
+
return TRUE;
}
static int blackbox_trigger = 0;
static char *blackbox_file_prefix = NULL;
static void
blackbox_logger(int32_t t, struct qb_log_callsite *cs, time_t timestamp, const char *msg)
{
if(cs && cs->priority < LOG_ERR) {
crm_write_blackbox(SIGTRAP, cs); /* Bypass the over-dumping logic */
} else {
crm_write_blackbox(0, cs);
}
}
static void
crm_control_blackbox(int nsig, bool enable)
{
if (blackbox_file_prefix == NULL) {
pid_t pid = getpid();
blackbox_file_prefix = malloc(NAME_MAX);
snprintf(blackbox_file_prefix, NAME_MAX, "%s/%s-%d", CRM_BLACKBOX_DIR, crm_system_name, pid);
}
if (enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 5 * 1024 * 1024); /* Any size change drops existing entries */
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE); /* Setting the size seems to disable it */
crm_notice("Initiated blackbox recorder: %s", blackbox_file_prefix);
/* Save to disk on abnormal termination */
crm_signal(SIGSEGV, crm_trigger_blackbox);
crm_signal(SIGABRT, crm_trigger_blackbox);
crm_signal(SIGILL, crm_trigger_blackbox);
crm_signal(SIGBUS, crm_trigger_blackbox);
crm_update_callsites();
blackbox_trigger = qb_log_custom_open(blackbox_logger, NULL, NULL, NULL);
qb_log_ctl(blackbox_trigger, QB_LOG_CONF_ENABLED, QB_TRUE);
crm_trace("Trigger: %d is %d %d", blackbox_trigger,
qb_log_ctl(blackbox_trigger, QB_LOG_CONF_STATE_GET, 0), QB_LOG_STATE_ENABLED);
crm_update_callsites();
} else if (!enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
}
}
void
crm_enable_blackbox(int nsig)
{
crm_control_blackbox(nsig, TRUE);
}
void
crm_disable_blackbox(int nsig)
{
crm_control_blackbox(nsig, FALSE);
}
void
crm_write_blackbox(int nsig, struct qb_log_callsite *cs)
{
static int counter = 1;
static time_t last = 0;
char buffer[NAME_MAX];
time_t now = time(NULL);
if (blackbox_file_prefix == NULL) {
return;
}
switch (nsig) {
case 0:
case SIGTRAP:
/* The graceful case - such as assertion failure or user request */
if (nsig == 0 && now == last) {
/* Prevent over-dumping */
return;
}
snprintf(buffer, NAME_MAX, "%s.%d", blackbox_file_prefix, counter++);
if (nsig == SIGTRAP) {
crm_notice("Blackbox dump requested, please see %s for contents", buffer);
} else if (cs) {
syslog(LOG_NOTICE,
"Problem detected at %s:%d (%s), please see %s for additional details",
cs->function, cs->lineno, cs->filename, buffer);
} else {
crm_notice("Problem detected, please see %s for additional details", buffer);
}
last = now;
qb_log_blackbox_write_to_file(buffer);
/* Flush the existing contents
* A size change would also work
*/
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
break;
default:
/* Do as little as possible, just try to get what we have out
* We logged the filename when the blackbox was enabled
*/
crm_signal(nsig, SIG_DFL);
qb_log_blackbox_write_to_file(blackbox_file_prefix);
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
raise(nsig);
break;
}
}
gboolean
crm_log_cli_init(const char *entity)
{
return crm_log_init(entity, LOG_ERR, FALSE, FALSE, 0, NULL, TRUE);
}
static const char *
crm_quark_to_string(uint32_t tag)
{
const char *text = g_quark_to_string(tag);
if (text) {
return text;
}
return "";
}
static void
crm_log_filter_source(int source, const char *trace_files, const char *trace_fns,
const char *trace_fmts, const char *trace_tags, const char *trace_blackbox,
struct qb_log_callsite *cs)
{
if (qb_log_ctl(source, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
return;
} else if (cs->tags != crm_trace_nonlog && source == QB_LOG_BLACKBOX) {
/* Blackbox gets everything if enabled */
qb_bit_set(cs->targets, source);
} else if (source == blackbox_trigger && blackbox_trigger > 0) {
/* Should this log message result in the blackbox being dumped */
if (cs->priority <= LOG_ERR) {
qb_bit_set(cs->targets, source);
} else if (trace_blackbox) {
char *key = g_strdup_printf("%s:%d", cs->function, cs->lineno);
if (strstr(trace_blackbox, key) != NULL) {
qb_bit_set(cs->targets, source);
}
free(key);
}
} else if (source == QB_LOG_SYSLOG) { /* No tracing to syslog */
if (cs->priority <= crm_log_priority && cs->priority <= crm_log_level) {
qb_bit_set(cs->targets, source);
}
/* Log file tracing options... */
} else if (cs->priority <= crm_log_level) {
qb_bit_set(cs->targets, source);
} else if (trace_files && strstr(trace_files, cs->filename) != NULL) {
qb_bit_set(cs->targets, source);
} else if (trace_fns && strstr(trace_fns, cs->function) != NULL) {
qb_bit_set(cs->targets, source);
} else if (trace_fmts && strstr(trace_fmts, cs->format) != NULL) {
qb_bit_set(cs->targets, source);
} else if (trace_tags
&& cs->tags != 0
&& cs->tags != crm_trace_nonlog && g_quark_to_string(cs->tags) != NULL) {
qb_bit_set(cs->targets, source);
}
}
static void
crm_log_filter(struct qb_log_callsite *cs)
{
int lpc = 0;
static int need_init = 1;
static const char *trace_fns = NULL;
static const char *trace_tags = NULL;
static const char *trace_fmts = NULL;
static const char *trace_files = NULL;
static const char *trace_blackbox = NULL;
if (need_init) {
need_init = 0;
trace_fns = getenv("PCMK_trace_functions");
trace_fmts = getenv("PCMK_trace_formats");
trace_tags = getenv("PCMK_trace_tags");
trace_files = getenv("PCMK_trace_files");
trace_blackbox = getenv("PCMK_trace_blackbox");
if (trace_tags != NULL) {
uint32_t tag;
char token[500];
const char *offset = NULL;
const char *next = trace_tags;
do {
offset = next;
next = strchrnul(offset, ',');
snprintf(token, 499, "%.*s", (int)(next - offset), offset);
tag = g_quark_from_string(token);
crm_info("Created GQuark %u from token '%s' in '%s'", tag, token, trace_tags);
if (next[0] != 0) {
next++;
}
} while (next != NULL && next[0] != 0);
}
}
cs->targets = 0; /* Reset then find targets to enable */
for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
crm_log_filter_source(lpc, trace_files, trace_fns, trace_fmts, trace_tags, trace_blackbox,
cs);
}
}
gboolean
crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
{
gboolean refilter = FALSE;
if (cs == NULL) {
return FALSE;
}
if (cs->priority != level) {
cs->priority = level;
refilter = TRUE;
}
if (cs->tags != tags) {
cs->tags = tags;
refilter = TRUE;
}
if (refilter) {
crm_log_filter(cs);
}
if (cs->targets == 0) {
return FALSE;
}
return TRUE;
}
void
crm_update_callsites(void)
{
static gboolean log = TRUE;
if (log) {
log = FALSE;
crm_debug
("Enabling callsites based on priority=%d, files=%s, functions=%s, formats=%s, tags=%s",
crm_log_level, getenv("PCMK_trace_files"), getenv("PCMK_trace_functions"),
getenv("PCMK_trace_formats"), getenv("PCMK_trace_tags"));
}
qb_log_filter_fn_set(crm_log_filter);
}
static gboolean
crm_tracing_enabled(void)
{
if (crm_log_level >= LOG_TRACE) {
return TRUE;
} else if (getenv("PCMK_trace_files") || getenv("PCMK_trace_functions")
|| getenv("PCMK_trace_formats") || getenv("PCMK_trace_tags")) {
return TRUE;
}
return FALSE;
}
static int
crm_priority2int(const char *name)
{
struct syslog_names {
const char *name;
int priority;
};
static struct syslog_names p_names[] = {
{"emerg", LOG_EMERG},
{"alert", LOG_ALERT},
{"crit", LOG_CRIT},
{"error", LOG_ERR},
{"warning", LOG_WARNING},
{"notice", LOG_NOTICE},
{"info", LOG_INFO},
{"debug", LOG_DEBUG},
{NULL, -1}
};
int lpc;
for (lpc = 0; name != NULL && p_names[lpc].name != NULL; lpc++) {
if (crm_str_eq(p_names[lpc].name, name, TRUE)) {
return p_names[lpc].priority;
}
}
return crm_log_priority;
}
gboolean
crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr,
int argc, char **argv, gboolean quiet)
{
int lpc = 0;
- const char *logfile = daemon_option("debugfile");
+ int32_t qb_facility = 0;
+ const char *logfile = daemon_option("logfile");
const char *facility = daemon_option("logfacility");
const char *f_copy = facility;
crm_is_daemon = daemon;
if (crm_trace_nonlog == 0) {
crm_trace_nonlog = g_quark_from_static_string("Pacemaker non-logging tracepoint");
}
umask(S_IWGRP | S_IWOTH | S_IROTH);
/* Redirect messages from glib functions to our handler */
#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 */
- if (facility == NULL) {
- facility = "daemon";
-
- } else if (safe_str_eq(facility, "none")) {
- facility = "daemon";
- quiet = TRUE;
- }
-
+ /* Who do we log as */
if (entity) {
free(crm_system_name);
crm_system_name = strdup(entity);
} else if (argc > 0 && argv != NULL) {
char *mutable = strdup(argv[0]);
char *modified = basename(mutable);
if (strstr(modified, "lt-") == modified) {
modified += 3;
}
free(crm_system_name);
crm_system_name = strdup(modified);
free(mutable);
} else if (crm_system_name == NULL) {
crm_system_name = strdup("Unknown");
}
setenv("PCMK_service", crm_system_name, 1);
- if (daemon_option_enabled(crm_system_name, "debug")) {
- /* Override the default setting */
- level = LOG_DEBUG;
+ /* Should we log to syslog */
+ if (facility == NULL) {
+ if(crm_is_daemon) {
+ facility = "daemon";
+ } else {
+ facility = "none";
+ }
+ set_daemon_option("logfacility", facility);
}
- if (daemon_option_enabled(crm_system_name, "stderr")) {
+ if (safe_str_eq(facility, "none")) {
+ quiet = TRUE;
+ qb_facility = qb_log_facility2int("daemon");
+
+ } else {
+ qb_facility = qb_log_facility2int(facility);
+ }
+
+ if (daemon_option_enabled(crm_system_name, "debug")) {
/* Override the default setting */
- to_stderr = TRUE;
+ level = LOG_DEBUG;
}
+ /* What lower threshold do we have for sending to syslog */
crm_log_priority = crm_priority2int(daemon_option("logpriority"));
crm_log_level = level;
- qb_log_init(crm_system_name, qb_log_facility2int(facility), level);
- qb_log_tags_stringify_fn_set(crm_quark_to_string);
+ qb_log_init(crm_system_name, qb_facility, crm_log_level);
- /* Set default format strings */
+ if (quiet) {
+ /* Nuke any syslog activity */
+ qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
+ }
+
+ /* Set format strings */
+ qb_log_tags_stringify_fn_set(crm_quark_to_string);
for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
set_format_string(lpc, crm_system_name);
}
+ /* Should we log to stderr */
+ if (daemon_option_enabled(crm_system_name, "stderr")) {
+ /* Override the default setting */
+ to_stderr = TRUE;
+ }
crm_enable_stderr(to_stderr);
+ /* Should we log to a file */
if (safe_str_eq("none", logfile)) {
/* No soup^Hlogs for you! */
} else if(crm_is_daemon) {
/* The daemons always get a log file, unless explicitly set to configured 'none' */
crm_add_logfile(logfile);
} else if(logfile) {
crm_add_logfile(logfile);
}
if (crm_is_daemon && daemon_option_enabled(crm_system_name, "blackbox")) {
crm_enable_blackbox(0);
}
+ /* Summary */
crm_trace("Quiet: %d, facility %s", quiet, f_copy);
- daemon_option("debugfile");
+ daemon_option("logfile");
daemon_option("logfacility");
- if (quiet) {
- /* Nuke any syslog activity */
- facility = NULL;
- qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
- }
-
- if (crm_is_daemon) {
- set_daemon_option("logfacility", facility);
- }
-
crm_update_callsites();
/* Ok, now we can start logging... */
if (quiet == FALSE && crm_is_daemon == FALSE) {
crm_log_args(argc, argv);
}
if (crm_is_daemon) {
const char *user = getenv("USER");
if (user != NULL && safe_str_neq(user, "root") && safe_str_neq(user, CRM_DAEMON_USER)) {
crm_trace("Not switching to corefile directory for %s", user);
crm_is_daemon = FALSE;
}
}
if (crm_is_daemon) {
int user = getuid();
const char *base = CRM_CORE_DIR;
struct passwd *pwent = getpwuid(user);
if (pwent == NULL) {
crm_perror(LOG_ERR, "Cannot get name for uid: %d", user);
} else if (safe_str_neq(pwent->pw_name, "root")
&& safe_str_neq(pwent->pw_name, CRM_DAEMON_USER)) {
crm_trace("Don't change active directory for regular user: %s", pwent->pw_name);
} else if (chdir(base) < 0) {
crm_perror(LOG_INFO, "Cannot change active directory to %s", base);
} else {
crm_info("Changed active directory to %s/%s", base, pwent->pw_name);
#if 0
{
char path[512];
snprintf(path, 512, "%s-%d", crm_system_name, getpid());
mkdir(path, 0750);
chdir(path);
crm_info("Changed active directory to %s/%s/%s", base, pwent->pw_name, path);
}
#endif
}
/* Original meanings from signal(7)
*
* Signal Value Action Comment
* SIGTRAP 5 Core Trace/breakpoint trap
* SIGUSR1 30,10,16 Term User-defined signal 1
* SIGUSR2 31,12,17 Term User-defined signal 2
*
* Our usage is as similar as possible
*/
mainloop_add_signal(SIGUSR1, crm_enable_blackbox);
mainloop_add_signal(SIGUSR2, crm_disable_blackbox);
mainloop_add_signal(SIGTRAP, crm_trigger_blackbox);
}
crm_xml_init(); /* Sets buffer allocation strategy */
return TRUE;
}
/* returns the old value */
unsigned int
set_crm_log_level(unsigned int level)
{
unsigned int old = crm_log_level;
crm_log_level = level;
crm_update_callsites();
crm_trace("New log level: %d", level);
return old;
}
void
crm_enable_stderr(int enable)
{
if (enable && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
crm_update_callsites();
} else if (enable == FALSE) {
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
}
}
void
crm_bump_log_level(int argc, char **argv)
{
static int args = TRUE;
int level = crm_log_level;
if (args && argc > 1) {
crm_log_args(argc, argv);
}
if (qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
set_crm_log_level(level + 1);
}
/* Enable after potentially logging the argstring, not before */
crm_enable_stderr(TRUE);
}
unsigned int
get_crm_log_level(void)
{
return crm_log_level;
}
#define ARGS_FMT "Invoked: %s"
void
crm_log_args(int argc, char **argv)
{
int lpc = 0;
int len = 0;
int restore = FALSE;
int existing_len = 0;
int line = __LINE__;
static int logged = 0;
char *arg_string = NULL;
struct qb_log_callsite *args_cs =
qb_log_callsite_get(__func__, __FILE__, ARGS_FMT, LOG_NOTICE, line, 0);
if (argc == 0 || argv == NULL || logged) {
return;
}
logged = 1;
qb_bit_set(args_cs->targets, QB_LOG_SYSLOG); /* Turn on syslog too */
restore = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_STATE_GET, 0);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
for (; lpc < argc; lpc++) {
if (argv[lpc] == NULL) {
break;
}
len = 2 + strlen(argv[lpc]); /* +1 space, +1 EOS */
arg_string = realloc(arg_string, len + existing_len);
existing_len += sprintf(arg_string + existing_len, "%s ", argv[lpc]);
}
qb_log_from_external_source(__func__, __FILE__, ARGS_FMT, LOG_NOTICE, line, 0, arg_string);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, restore);
free(arg_string);
}
const char *
pcmk_errorname(int rc)
{
int error = ABS(rc);
switch (error) {
case E2BIG: return "E2BIG";
case EACCES: return "EACCES";
case EADDRINUSE: return "EADDRINUSE";
case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
case EAFNOSUPPORT: return "EAFNOSUPPORT";
case EAGAIN: return "EAGAIN";
case EALREADY: return "EALREADY";
case EBADF: return "EBADF";
case EBADMSG: return "EBADMSG";
case EBUSY: return "EBUSY";
case ECANCELED: return "ECANCELED";
case ECHILD: return "ECHILD";
case ECOMM: return "ECOMM";
case ECONNABORTED: return "ECONNABORTED";
case ECONNREFUSED: return "ECONNREFUSED";
case ECONNRESET: return "ECONNRESET";
/* case EDEADLK: return "EDEADLK"; */
case EDESTADDRREQ: return "EDESTADDRREQ";
case EDOM: return "EDOM";
case EDQUOT: return "EDQUOT";
case EEXIST: return "EEXIST";
case EFAULT: return "EFAULT";
case EFBIG: return "EFBIG";
case EHOSTDOWN: return "EHOSTDOWN";
case EHOSTUNREACH: return "EHOSTUNREACH";
case EIDRM: return "EIDRM";
case EILSEQ: return "EILSEQ";
case EINPROGRESS: return "EINPROGRESS";
case EINTR: return "EINTR";
case EINVAL: return "EINVAL";
case EIO: return "EIO";
case EISCONN: return "EISCONN";
case EISDIR: return "EISDIR";
case ELIBACC: return "ELIBACC";
case ELOOP: return "ELOOP";
case EMFILE: return "EMFILE";
case EMLINK: return "EMLINK";
case EMSGSIZE: return "EMSGSIZE";
case EMULTIHOP: return "EMULTIHOP";
case ENAMETOOLONG: return "ENAMETOOLONG";
case ENETDOWN: return "ENETDOWN";
case ENETRESET: return "ENETRESET";
case ENETUNREACH: return "ENETUNREACH";
case ENFILE: return "ENFILE";
case ENOBUFS: return "ENOBUFS";
case ENODATA: return "ENODATA";
case ENODEV: return "ENODEV";
case ENOENT: return "ENOENT";
case ENOEXEC: return "ENOEXEC";
case ENOKEY: return "ENOKEY";
case ENOLCK: return "ENOLCK";
case ENOLINK: return "ENOLINK";
case ENOMEM: return "ENOMEM";
case ENOMSG: return "ENOMSG";
case ENOPROTOOPT: return "ENOPROTOOPT";
case ENOSPC: return "ENOSPC";
case ENOSR: return "ENOSR";
case ENOSTR: return "ENOSTR";
case ENOSYS: return "ENOSYS";
case ENOTBLK: return "ENOTBLK";
case ENOTCONN: return "ENOTCONN";
case ENOTDIR: return "ENOTDIR";
case ENOTEMPTY: return "ENOTEMPTY";
case ENOTSOCK: return "ENOTSOCK";
/* case ENOTSUP: return "ENOTSUP"; */
case ENOTTY: return "ENOTTY";
case ENOTUNIQ: return "ENOTUNIQ";
case ENXIO: return "ENXIO";
case EOPNOTSUPP: return "EOPNOTSUPP";
case EOVERFLOW: return "EOVERFLOW";
case EPERM: return "EPERM";
case EPFNOSUPPORT: return "EPFNOSUPPORT";
case EPIPE: return "EPIPE";
case EPROTO: return "EPROTO";
case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
case EPROTOTYPE: return "EPROTOTYPE";
case ERANGE: return "ERANGE";
case EREMOTE: return "EREMOTE";
case EREMOTEIO: return "EREMOTEIO";
case EROFS: return "EROFS";
case ESHUTDOWN: return "ESHUTDOWN";
case ESPIPE: return "ESPIPE";
case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
case ESRCH: return "ESRCH";
case ESTALE: return "ESTALE";
case ETIME: return "ETIME";
case ETIMEDOUT: return "ETIMEDOUT";
case ETXTBSY: return "ETXTBSY";
case EUNATCH: return "EUNATCH";
case EUSERS: return "EUSERS";
/* case EWOULDBLOCK: return "EWOULDBLOCK"; */
case EXDEV: return "EXDEV";
#ifdef EBADE
/* Not available on OSX */
case EBADE: return "EBADE";
case EBADFD: return "EBADFD";
case EBADSLT: return "EBADSLT";
case EDEADLOCK: return "EDEADLOCK";
case EBADR: return "EBADR";
case EBADRQC: return "EBADRQC";
case ECHRNG: return "ECHRNG";
#ifdef EISNAM /* Not available on Illumos/Solaris */
case EISNAM: return "EISNAM";
case EKEYEXPIRED: return "EKEYEXPIRED";
case EKEYREJECTED: return "EKEYREJECTED";
case EKEYREVOKED: return "EKEYREVOKED";
#endif
case EL2HLT: return "EL2HLT";
case EL2NSYNC: return "EL2NSYNC";
case EL3HLT: return "EL3HLT";
case EL3RST: return "EL3RST";
case ELIBBAD: return "ELIBBAD";
case ELIBMAX: return "ELIBMAX";
case ELIBSCN: return "ELIBSCN";
case ELIBEXEC: return "ELIBEXEC";
#ifdef ENOMEDIUM /* Not available on Illumos/Solaris */
case ENOMEDIUM: return "ENOMEDIUM";
case EMEDIUMTYPE: return "EMEDIUMTYPE";
#endif
case ENONET: return "ENONET";
case ENOPKG: return "ENOPKG";
case EREMCHG: return "EREMCHG";
case ERESTART: return "ERESTART";
case ESTRPIPE: return "ESTRPIPE";
#ifdef EUCLEAN /* Not available on Illumos/Solaris */
case EUCLEAN: return "EUCLEAN";
#endif
case EXFULL: return "EXFULL";
#endif
case pcmk_err_generic: return "pcmk_err_generic";
case pcmk_err_no_quorum: return "pcmk_err_no_quorum";
case pcmk_err_schema_validation: return "pcmk_err_schema_validation";
case pcmk_err_transform_failed: return "pcmk_err_transform_failed";
case pcmk_err_old_data: return "pcmk_err_old_data";
case pcmk_err_diff_failed: return "pcmk_err_diff_failed";
case pcmk_err_diff_resync: return "pcmk_err_diff_resync";
case pcmk_err_cib_modified: return "pcmk_err_cib_modified";
case pcmk_err_cib_backup: return "pcmk_err_cib_backup";
case pcmk_err_cib_save: return "pcmk_err_cib_save";
}
return "Unknown";
}
const char *
pcmk_strerror(int rc)
{
int error = abs(rc);
if (error == 0) {
return "OK";
} else if (error < PCMK_ERROR_OFFSET) {
return strerror(error);
}
switch (error) {
case pcmk_err_generic:
return "Generic Pacemaker error";
case pcmk_err_no_quorum:
return "Operation requires quorum";
case pcmk_err_schema_validation:
return "Update does not conform to the configured schema";
case pcmk_err_transform_failed:
return "Schema transform failed";
case pcmk_err_old_data:
return "Update was older than existing configuration";
case pcmk_err_diff_failed:
return "Application of an update diff failed";
case pcmk_err_diff_resync:
return "Application of an update diff failed, requesting a full refresh";
case pcmk_err_cib_modified:
return "The on-disk configuration was manually modified";
case pcmk_err_cib_backup:
return "Could not archive the previous configuration";
case pcmk_err_cib_save:
return "Could not save the new configuration to disk";
case pcmk_err_schema_unchanged:
return "Schema is already the latest available";
/* The following cases will only be hit on systems for which they are non-standard */
/* coverity[dead_error_condition] False positive on non-Linux */
case ENOTUNIQ:
return "Name not unique on network";
/* coverity[dead_error_condition] False positive on non-Linux */
case ECOMM:
return "Communication error on send";
/* coverity[dead_error_condition] False positive on non-Linux */
case ELIBACC:
return "Can not access a needed shared library";
/* coverity[dead_error_condition] False positive on non-Linux */
case EREMOTEIO:
return "Remote I/O error";
/* coverity[dead_error_condition] False positive on non-Linux */
case EUNATCH:
return "Protocol driver not attached";
/* coverity[dead_error_condition] False positive on non-Linux */
case ENOKEY:
return "Required key not available";
}
crm_err("Unknown error code: %d", rc);
return "Unknown error";
}
const char *
bz2_strerror(int rc)
{
/* http://www.bzip.org/1.0.3/html/err-handling.html */
switch (rc) {
case BZ_OK:
case BZ_RUN_OK:
case BZ_FLUSH_OK:
case BZ_FINISH_OK:
case BZ_STREAM_END:
return "Ok";
case BZ_CONFIG_ERROR:
return "libbz2 has been improperly compiled on your platform";
case BZ_SEQUENCE_ERROR:
return "library functions called in the wrong order";
case BZ_PARAM_ERROR:
return "parameter is out of range or otherwise incorrect";
case BZ_MEM_ERROR:
return "memory allocation failed";
case BZ_DATA_ERROR:
return "data integrity error is detected during decompression";
case BZ_DATA_ERROR_MAGIC:
return "the compressed stream does not start with the correct magic bytes";
case BZ_IO_ERROR:
return "error reading or writing in the compressed file";
case BZ_UNEXPECTED_EOF:
return "compressed file finishes before the logical end of stream is detected";
case BZ_OUTBUFF_FULL:
return "output data will not fit into the buffer provided";
}
return "Unknown error";
}
void
crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix,
const char *output)
{
const char *next = NULL;
const char *offset = NULL;
if (output == NULL) {
level = LOG_DEBUG;
output = "-- empty --";
}
next = output;
do {
offset = next;
next = strchrnul(offset, '\n');
do_crm_log_alias(level, file, function, line, "%s [ %.*s ]", prefix,
(int)(next - offset), offset);
if (next[0] != 0) {
next++;
}
} while (next != NULL && next[0] != 0);
}
diff --git a/mcp/corosync.c b/mcp/corosync.c
index cae8cf9c0c..24f5c22b5b 100644
--- a/mcp/corosync.c
+++ b/mcp/corosync.c
@@ -1,483 +1,474 @@
/*
* Copyright (C) 2010 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <crm_internal.h>
#include <pacemaker.h>
#include <sys/utsname.h>
#include <sys/stat.h> /* for calls to stat() */
#include <libgen.h> /* For basename() and dirname() */
#include <sys/types.h>
#include <pwd.h> /* For getpwname() */
#include <corosync/hdb.h>
#include <corosync/cfg.h>
#include <corosync/cpg.h>
#if HAVE_CONFDB
# include <corosync/confdb.h>
#endif
#include <crm/cluster/internal.h>
#include <crm/common/mainloop.h>
#if SUPPORT_CMAN
# include <libcman.h>
#endif
#if HAVE_CMAP
# include <corosync/cmap.h>
#endif
enum cluster_type_e stack = pcmk_cluster_unknown;
static corosync_cfg_handle_t cfg_handle;
/* =::=::=::= CFG - Shutdown stuff =::=::=::= */
static void
cfg_shutdown_callback(corosync_cfg_handle_t h, corosync_cfg_shutdown_flags_t flags)
{
crm_info("Corosync wants to shut down: %s",
(flags == COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE) ? "immediate" :
(flags == COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS) ? "forced" : "optional");
/* Never allow corosync to shut down while we're running */
corosync_cfg_replyto_shutdown(h, COROSYNC_CFG_SHUTDOWN_FLAG_NO);
}
static corosync_cfg_callbacks_t cfg_callbacks = {
.corosync_cfg_shutdown_callback = cfg_shutdown_callback,
};
static int
pcmk_cfg_dispatch(gpointer user_data)
{
corosync_cfg_handle_t *handle = (corosync_cfg_handle_t *) user_data;
cs_error_t rc = corosync_cfg_dispatch(*handle, CS_DISPATCH_ALL);
if (rc != CS_OK) {
return -1;
}
return 0;
}
static void
cfg_connection_destroy(gpointer user_data)
{
crm_err("Connection destroyed");
cfg_handle = 0;
pcmk_shutdown(SIGTERM);
}
gboolean
cluster_disconnect_cfg(void)
{
if (cfg_handle) {
corosync_cfg_finalize(cfg_handle);
cfg_handle = 0;
}
pcmk_shutdown(SIGTERM);
return TRUE;
}
#define cs_repeat(counter, max, code) do { \
code; \
if(rc == CS_ERR_TRY_AGAIN || rc == CS_ERR_QUEUE_FULL) { \
counter++; \
crm_debug("Retrying operation after %ds", counter); \
sleep(counter); \
} else { \
break; \
} \
} while(counter < max)
gboolean
cluster_connect_cfg(uint32_t * nodeid)
{
cs_error_t rc;
int fd = 0, retries = 0;
static struct mainloop_fd_callbacks cfg_fd_callbacks = {
.dispatch = pcmk_cfg_dispatch,
.destroy = cfg_connection_destroy,
};
cs_repeat(retries, 30, rc = corosync_cfg_initialize(&cfg_handle, &cfg_callbacks));
if (rc != CS_OK) {
crm_err("corosync cfg init error %d", rc);
return FALSE;
}
rc = corosync_cfg_fd_get(cfg_handle, &fd);
if (rc != CS_OK) {
crm_err("corosync cfg fd_get error %d", rc);
goto bail;
}
retries = 0;
cs_repeat(retries, 30, rc = corosync_cfg_local_get(cfg_handle, nodeid));
if (rc != CS_OK) {
crm_err("corosync cfg local_get error %d", rc);
goto bail;
}
crm_debug("Our nodeid: %d", *nodeid);
mainloop_add_fd("corosync-cfg", G_PRIORITY_DEFAULT, fd, &cfg_handle, &cfg_fd_callbacks);
return TRUE;
bail:
corosync_cfg_finalize(cfg_handle);
return FALSE;
}
/* =::=::=::= Configuration =::=::=::= */
#if HAVE_CONFDB
static int
get_config_opt(confdb_handle_t config,
hdb_handle_t object_handle, const char *key, char **value, const char *fallback)
{
size_t len = 0;
char *env_key = NULL;
const char *env_value = NULL;
char buffer[256];
if (*value) {
free(*value);
*value = NULL;
}
if (object_handle > 0) {
if (CS_OK == confdb_key_get(config, object_handle, key, strlen(key), &buffer, &len)) {
*value = strdup(buffer);
}
}
if (*value) {
crm_info("Found '%s' for option: %s", *value, key);
return 0;
}
env_key = crm_concat("HA", key, '_');
env_value = getenv(env_key);
free(env_key);
if (*value) {
crm_info("Found '%s' in ENV for option: %s", *value, key);
*value = strdup(env_value);
return 0;
}
if (fallback) {
crm_info("Defaulting to '%s' for option: %s", fallback, key);
*value = strdup(fallback);
} else {
crm_info("No default for option: %s", key);
}
return -1;
}
static confdb_handle_t
config_find_init(confdb_handle_t config)
{
cs_error_t rc = CS_OK;
confdb_handle_t local_handle = OBJECT_PARENT_HANDLE;
rc = confdb_object_find_start(config, local_handle);
if (rc == CS_OK) {
return local_handle;
} else {
crm_err("Couldn't create search context: %d", rc);
}
return 0;
}
static hdb_handle_t
config_find_next(confdb_handle_t config, const char *name, confdb_handle_t top_handle)
{
cs_error_t rc = CS_OK;
hdb_handle_t local_handle = 0;
if (top_handle == 0) {
crm_err("Couldn't search for %s: no valid context", name);
return 0;
}
crm_trace("Searching for %s in " HDB_X_FORMAT, name, top_handle);
rc = confdb_object_find(config, top_handle, name, strlen(name), &local_handle);
if (rc != CS_OK) {
crm_info("No additional configuration supplied for: %s", name);
local_handle = 0;
} else {
crm_info("Processing additional %s options...", name);
}
return local_handle;
}
#else
static int
get_config_opt(uint64_t unused, cmap_handle_t object_handle, const char *key, char **value,
const char *fallback)
{
int rc = 0, retries = 0;
cs_repeat(retries, 5, rc = cmap_get_string(object_handle, key, value));
if (rc != CS_OK) {
crm_trace("Search for %s failed %d, defaulting to %s", key, rc, fallback);
if (fallback) {
*value = strdup(fallback);
} else {
*value = NULL;
}
}
crm_trace("%s: %s", key, *value);
return rc;
}
#endif
#if HAVE_CONFDB
# define KEY_PREFIX ""
#elif HAVE_CMAP
# define KEY_PREFIX "logging."
#endif
gboolean
mcp_read_config(void)
{
int rc = CS_OK;
int retries = 0;
- gboolean have_log = FALSE;
const char *const_value = NULL;
- char *logging_debug = NULL;
- char *logging_logfile = NULL;
- char *logging_to_logfile = NULL;
- char *logging_to_syslog = NULL;
- char *logging_syslog_facility = NULL;
-
#if HAVE_CONFDB
char *value = NULL;
confdb_handle_t config = 0;
confdb_handle_t top_handle = 0;
hdb_handle_t local_handle;
static confdb_callbacks_t callbacks = { };
do {
rc = confdb_initialize(&config, &callbacks);
if (rc != CS_OK) {
retries++;
printf("confdb connection setup failed: %s. Retrying in %ds\n", ais_error2text(rc), retries);
crm_info("confdb connection setup failed: %s. Retrying in %ds", ais_error2text(rc), retries);
sleep(retries);
} else {
break;
}
} while (retries < 5);
#elif HAVE_CMAP
cmap_handle_t local_handle;
uint64_t config = 0;
/* There can be only one (possibility if confdb isn't around) */
do {
rc = cmap_initialize(&local_handle);
if (rc != CS_OK) {
retries++;
printf("cmap connection setup failed: %s. Retrying in %ds\n", cs_strerror(rc), retries);
crm_info("cmap connection setup failed: %s. Retrying in %ds", cs_strerror(rc), retries);
sleep(retries);
} else {
break;
}
} while (retries < 5);
#endif
if (rc != CS_OK) {
printf("Could not connect to Cluster Configuration Database API, error %d\n", rc);
crm_warn("Could not connect to Cluster Configuration Database API, error %d", rc);
return FALSE;
}
stack = get_cluster_type();
crm_info("Reading configure for stack: %s", name_for_cluster_type(stack));
/* =::=::= Should we be here =::=::= */
if (stack == pcmk_cluster_corosync) {
set_daemon_option("cluster_type", "corosync");
set_daemon_option("quorum_type", "corosync");
#if HAVE_CONFDB
} else if (stack == pcmk_cluster_cman) {
set_daemon_option("cluster_type", "cman");
set_daemon_option("quorum_type", "cman");
enable_crmd_as_root(TRUE);
} else if (stack == pcmk_cluster_classic_ais) {
set_daemon_option("cluster_type", "openais");
set_daemon_option("quorum_type", "pcmk");
/* Look for a service block to indicate our plugin is loaded */
top_handle = config_find_init(config);
local_handle = config_find_next(config, "service", top_handle);
while (local_handle) {
get_config_opt(config, local_handle, "name", &value, NULL);
if (safe_str_eq("pacemaker", value)) {
get_config_opt(config, local_handle, "ver", &value, "0");
if (safe_str_eq(value, "1")) {
get_config_opt(config, local_handle, "use_logd", &value, "no");
set_daemon_option("use_logd", value);
set_daemon_option("LOGD", value);
get_config_opt(config, local_handle, "use_mgmtd", &value, "no");
enable_mgmtd(crm_is_true(value));
} else {
crm_err("We can only start Pacemaker from init if using version 1"
" of the Pacemaker plugin for Corosync. Terminating.");
crm_exit(DAEMON_RESPAWN_STOP);
}
break;
}
local_handle = config_find_next(config, "service", top_handle);
}
free(value);
#endif
} else {
crm_err("Unsupported stack type: %s", name_for_cluster_type(stack));
return FALSE;
}
#if HAVE_CONFDB
top_handle = config_find_init(config);
local_handle = config_find_next(config, "logging", top_handle);
#endif
/* =::=::= Logging =::=::= */
- get_config_opt(config, local_handle, KEY_PREFIX "debug", &logging_debug, "off");
+ if (daemon_option("debug")) {
+ /* Syslog logging is already setup by crm_log_init() */
+
+ } else {
+ /* Check corosync */
+ char *debug_enabled = NULL;
+
+ get_config_opt(config, local_handle, KEY_PREFIX "debug", &debug_enabled, "off");
+
+ if (crm_is_true(debug_enabled)) {
+ set_daemon_option("debug", "1");
+ if (get_crm_log_level() < LOG_DEBUG) {
+ set_crm_log_level(LOG_DEBUG);
+ }
+
+ } else {
+ set_daemon_option("debug", "0");
+ }
+
+ free(debug_enabled);
+ }
const_value = daemon_option("debugfile");
- if (const_value) {
- logging_to_logfile = strdup("on");
- logging_logfile = strdup(const_value);
- crm_trace("Using debugfile setting from the environment: %s", logging_logfile);
+ if (daemon_option("logfile")) {
+ /* File logging is already setup by crm_log_init() */
+
+ } else if(const_value) {
+ /* From when we cared what options heartbeat used */
+ set_daemon_option("logfile", const_value);
+ crm_add_logfile(const_value);
} else {
- get_config_opt(config, local_handle, KEY_PREFIX "to_logfile", &logging_to_logfile, "off");
- get_config_opt(config, local_handle, KEY_PREFIX "logfile", &logging_logfile,
- "/var/log/pacemaker");
- }
+ /* Check corosync */
+ char *logfile = NULL;
+ char *logfile_enabled = NULL;
- const_value = daemon_option("logfacility");
- if (const_value) {
- logging_syslog_facility = strdup(const_value);
- crm_trace("Using logfacility setting from the environment: %s", logging_syslog_facility);
+ get_config_opt(config, local_handle, KEY_PREFIX "to_logfile", &logfile_enabled, "on");
+ get_config_opt(config, local_handle, KEY_PREFIX "logfile", &logfile, "/var/log/pacemaker.log");
+
+ if (crm_is_true(logfile_enabled) == FALSE) {
+ crm_trace("File logging disabled in corosync");
+
+ } else if (crm_add_logfile(logfile)) {
+ set_daemon_option("logfile", logfile);
- if (safe_str_eq(logging_syslog_facility, "none")) {
- logging_to_syslog = strdup("off");
} else {
- logging_to_syslog = strdup("on");
+ crm_err("Couldn't create logfile: %s", logfile);
+ set_daemon_option("logfile", "none");
}
+ free(logfile);
+ free(logfile_enabled);
+ }
+
+ if (daemon_option("logfacility")) {
+ /* Syslog logging is already setup by crm_log_init() */
+
} else {
- get_config_opt(config, local_handle, KEY_PREFIX "to_syslog", &logging_to_syslog, "on");
- get_config_opt(config, local_handle, KEY_PREFIX "syslog_facility", &logging_syslog_facility,
- "daemon");
+ /* Check corosync */
+ char *syslog_enabled = NULL;
+ char *syslog_facility = NULL;
+
+ get_config_opt(config, local_handle, KEY_PREFIX "to_syslog", &syslog_enabled, "on");
+ get_config_opt(config, local_handle, KEY_PREFIX "syslog_facility", &syslog_facility, "daemon");
+
+ if (crm_is_true(syslog_enabled) == FALSE) {
+ qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
+ set_daemon_option("logfacility", "none");
+
+ } else {
+ qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(syslog_facility));
+ qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
+ set_daemon_option("logfacility", syslog_facility);
+ }
+
+ free(syslog_enabled);
+ free(syslog_facility);
}
#if HAVE_CONFDB
confdb_finalize(config);
#elif HAVE_CMAP
if(local_handle){
gid_t gid = 0;
if (crm_user_lookup(CRM_DAEMON_USER, NULL, &gid) < 0) {
crm_warn("No group found for user %s", CRM_DAEMON_USER);
} else {
char key[PATH_MAX];
snprintf(key, PATH_MAX, "uidgid.gid.%u", gid);
rc = cmap_set_uint8(local_handle, key, 1);
crm_notice("Configured corosync to accept connections from group %u: %s (%d)",
gid, ais_error2text(rc), rc);
}
}
cmap_finalize(local_handle);
#endif
- if (daemon_option("debug")) {
- crm_trace("Using debug setting from the environment: %s", daemon_option("debug"));
- if (get_crm_log_level() < LOG_DEBUG && daemon_option_enabled("pacemakerd", "debug")) {
- set_crm_log_level(LOG_DEBUG);
- }
-
- } else if (crm_is_true(logging_debug)) {
- set_daemon_option("debug", "1");
- if (get_crm_log_level() < LOG_DEBUG) {
- set_crm_log_level(LOG_DEBUG);
- }
-
- } else {
- set_daemon_option("debug", "0");
- }
-
- if (crm_is_true(logging_to_logfile)) {
- if (crm_add_logfile(logging_logfile)) {
- /* What a cluster fsck, eventually we need to mandate /one/ */
- set_daemon_option("debugfile", logging_logfile);
- set_daemon_option("DEBUGLOG", logging_logfile);
- have_log = TRUE;
-
- } else {
- crm_err("Couldn't create logfile: %s", logging_logfile);
- }
- }
-
- if (have_log && crm_is_true(logging_to_syslog) == FALSE) {
- qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
- free(logging_syslog_facility);
- logging_syslog_facility = strdup("none");
- crm_info("User configured file based logging and explicitly disabled syslog.");
-
- } else if (crm_is_true(logging_to_syslog) == FALSE) {
- crm_err("Please enable some sort of logging, either 'to_logfile: on' or 'to_syslog: on'.");
- crm_err("If you use file logging, be sure to also define a value for 'logfile'");
-
- } else {
- qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(logging_syslog_facility));
- }
-
- set_daemon_option("logfacility", logging_syslog_facility);
- setenv("HA_LOGFACILITY", logging_syslog_facility, 1);
-
- free(logging_debug);
- free(logging_logfile);
- free(logging_to_logfile);
- free(logging_to_syslog);
- free(logging_syslog_facility);
return TRUE;
}
diff --git a/mcp/pacemaker.sysconfig b/mcp/pacemaker.sysconfig
index bd6a15af60..4b1fdff12a 100644
--- a/mcp/pacemaker.sysconfig
+++ b/mcp/pacemaker.sysconfig
@@ -1,96 +1,96 @@
# For non-systemd based systems, prefix export to each enabled line
# Turn on special handling for CMAN clusters in the init script
# Without this, fenced (and by inference, cman) cannot reliably be made to shut down
# PCMK_STACK=cman
#==#==# Variables that control logging
# Enable debug logging globally or per-subsystem
# Multiple subsystems may me listed separated by commas
# eg. PCMK_debug=crmd,pengine
# PCMK_debug=yes|no|crmd|pengine|cib|stonith-ng|attrd|pacemakerd
# Send INFO (and higher) messages to the named log file
# Additional messages may also appear here depending on any configured debug and trace settings
# By default Pacemaker will inherit the logfile specified in corosync.conf
-# PCMK_debugfile=/var/log/pacemaker.log
+# PCMK_logfile=/var/log/pacemaker.log
# Specify an alternate syslog target for NOTICE (and higher) messages
# Use 'none' to disable - not recommended
# The default value is 'daemon'
# PCMK_logfacility=none|daemon|user|local0|local1|local2|local3|local4|local5|local6|local7
# Send all messages up-to-and-including the configured priority to syslog
# A value of 'info' will be far too verbose for most installations and 'debug' is almost certain to send you blind
# The default value is 'notice'
# PCMK_logpriority=emerg|alert|crit|error|warning|notice|info|debug
# Log all messages from a comma-separated list of functions
# PCMK_trace_functions=function1,function2,function3
# Log all messages from a comma-separated list of files (no path)
# Supports wildcards eg. PCMK_trace_files=prefix*.c
# PCMK_trace_files=file.c,other.h
# Log all messages matching comma-separated list of formats
# PCMK_trace_formats="Sent delete %d"
# Log all messages from a comma-separated list of tags
# PCMK_trace_tags=tag1,tag2
# Dump the blackbox whenever the message at function and line is printed
# eg. PCMK_trace_blackbox=te_graph_trigger:223,unpack_clone:81
# PCMK_trace_blackbox=fn:line,fn2:line2,...
# Enable blackbox logging globally or per-subsystem
# The blackbox contains a rolling buffer of all logs (including info+debug+trace)
# and is written after a crash, assertion failure and/or when SIGTRAP is received
#
# The blackbox recorder can also be enabled for Pacemaker daemons at runtime by
# sending SIGUSR1 (or SIGTRAP), and disabled by sending SIGUSR2
#
# Multiple subsystems may me listed separated by commas
# eg. PCMK_blackbox=crmd,pengine
# PCMK_blackbox=yes|no|crmd|pengine|cib|stonith-ng|attrd|pacemakerd
#==#==# Advanced use only
# Enable this for compatibility with older corosync (prior to 2.0)
# based clusters which used the nodes uname as its uuid also
# PCMK_uname_is_uuid=no
# Specify an alternate location for RNG schemas and XSL transforms
# Mostly only useful for developer testing
# PCMK_schema_directory=/some/path
# Enable this for rebooting this machine at the time of process (subsystem) failure
# PCMK_fail_fast=no
#==#==# Pacemaker Remote
# Use a custom directory for finding the authkey.
# PCMK_authkey_location=/etc/pacemaker/authkey
#
# Specify a custom port for Pacemaker Remote connections
# PCMK_remote_port=3121
#==#==# IPC
# Force use of a particular class of IPC connection
# PCMK_ipc_type=shared-mem|socket|posix|sysv
# Specify an IPC buffer size in bytes
# Useful when connecting to really big clusters that exceed the default 20k buffer
# PCMK_ipc_buffer=20480
#==#==# Profiling and memory leak testing
# Variables for running child daemons under valgrind and/or checking for memory problems
# G_SLICE=always-malloc
# MALLOC_PERTURB_=221 # or 0
# MALLOC_CHECK_=3 # or 0,1,2
# PCMK_valgrind_enabled=yes
# PCMK_valgrind_enabled=cib,crmd
# PCMK_callgrind_enabled=yes
# PCMK_callgrind_enabled=cib,crmd
# VALGRIND_OPTS="--leak-check=full --trace-children=no --num-callers=25 --log-file=/var/lib/pacemaker/valgrind-%p --suppressions=/usr/share/pacemaker/tests/valgrind-pcmk.suppressions --gen-suppressions=all"

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:37 PM (2 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002718
Default Alt Text
(80 KB)

Event Timeline