Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4624612
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
80 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 8, 6:37 PM (6 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002718
Default Alt Text
(80 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment