Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4639129
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/mcp/corosync.c b/mcp/corosync.c
index 13c3565730..999f42f3b8 100644
--- a/mcp/corosync.c
+++ b/mcp/corosync.c
@@ -1,670 +1,675 @@
/*
* 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/common/cluster.h>
#if SUPPORT_CMAN
# include <libcman.h>
#endif
#if HAVE_CMAP
# include <corosync/cmap.h>
#endif
static struct cpg_name cpg_group = {
.length = 0,
.value[0] = 0,
};
gboolean use_cman = FALSE;
static cpg_handle_t cpg_handle;
static corosync_cfg_handle_t cfg_handle;
static corosync_cfg_state_notification_t cfg_buffer;
/* =::=::=::= 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,
.corosync_cfg_state_track_callback = NULL,
};
static gboolean
pcmk_cfg_dispatch(int sender, 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 FALSE;
}
return TRUE;
}
static void
cfg_connection_destroy(gpointer user_data)
{
crm_err("Connection destroyed");
cfg_handle = 0;
pcmk_shutdown(SIGTERM);
return;
}
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) { \
counter++; \
crm_debug("Retrying operation after %ds", counter); \
sleep(counter); \
} \
} while(rc == CS_ERR_TRY_AGAIN && counter < max)
gboolean
cluster_connect_cfg(uint32_t * nodeid)
{
cs_error_t rc;
int fd = 0, retries = 0;
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);
retries = 0;
cs_repeat(retries, 30, rc = corosync_cfg_state_track(cfg_handle, 0, &cfg_buffer));
if (rc != CS_OK) {
crm_err("corosync cfg stack_track error %d", rc);
goto bail;
}
crm_debug("Adding fd=%d to mainloop", fd);
G_main_add_fd(G_PRIORITY_HIGH, fd, FALSE, pcmk_cfg_dispatch, &cfg_handle,
cfg_connection_destroy);
return TRUE;
bail:
corosync_cfg_finalize(cfg_handle);
return FALSE;
}
/* =::=::=::= CPG - Closed Process Group Messaging =::=::=::= */
static gboolean
pcmk_cpg_dispatch(int sender, gpointer user_data)
{
cpg_handle_t *handle = (cpg_handle_t *) user_data;
cs_error_t rc = cpg_dispatch(*handle, CS_DISPATCH_ALL);
if (rc != CS_OK) {
return FALSE;
}
return TRUE;
}
static void
cpg_connection_destroy(gpointer user_data)
{
crm_err("Connection destroyed");
cpg_handle = 0;
return;
}
static void
pcmk_cpg_deliver(cpg_handle_t handle,
const struct cpg_name *groupName,
uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len)
{
if (nodeid != local_nodeid) {
uint32_t procs = 0;
xmlNode *xml = string2xml(msg);
const char *uname = crm_element_value(xml, "uname");
crm_element_value_int(xml, "proclist", (int *)&procs);
/* crm_debug("Got proclist %.32x from %s", procs, uname); */
if (update_node_processes(nodeid, uname, procs)) {
update_process_clients();
}
}
}
static void
pcmk_cpg_membership(cpg_handle_t handle,
const struct cpg_name *groupName,
const struct cpg_address *member_list, size_t member_list_entries,
const struct cpg_address *left_list, size_t left_list_entries,
const struct cpg_address *joined_list, size_t joined_list_entries)
{
/* Don't care about CPG membership */
update_process_peers();
}
cpg_callbacks_t cpg_callbacks = {
.cpg_deliver_fn = pcmk_cpg_deliver,
.cpg_confchg_fn = pcmk_cpg_membership,
};
gboolean
cluster_disconnect_cpg(void)
{
if (cpg_handle) {
cpg_finalize(cpg_handle);
cpg_handle = 0;
}
return TRUE;
}
gboolean
cluster_connect_cpg(void)
{
cs_error_t rc;
unsigned int nodeid;
int fd;
int retries = 0;
strcpy(cpg_group.value, "pcmk");
cpg_group.length = strlen(cpg_group.value) + 1;
retries = 0;
cs_repeat(retries, 30, rc = cpg_initialize(&cpg_handle, &cpg_callbacks));
if (rc != CS_OK) {
crm_err("corosync cpg init error %d", rc);
return FALSE;
}
rc = cpg_fd_get(cpg_handle, &fd);
if (rc != CS_OK) {
crm_err("corosync cpg fd_get error %d", rc);
goto bail;
}
retries = 0;
cs_repeat(retries, 30, rc = cpg_local_get(cpg_handle, &nodeid));
if (rc != CS_OK) {
crm_err("corosync cpg local_get error %d", rc);
goto bail;
}
crm_debug("Our nodeid: %d", nodeid);
retries = 0;
cs_repeat(retries, 30, rc = cpg_join(cpg_handle, &cpg_group));
if (rc != CS_OK) {
crm_err("Could not join the CPG group '%s': %d", crm_system_name, rc);
goto bail;
}
crm_debug("Adding fd=%d to mainloop", fd);
G_main_add_fd(G_PRIORITY_HIGH, fd, FALSE, pcmk_cpg_dispatch, &cpg_handle,
cpg_connection_destroy);
return TRUE;
bail:
cpg_finalize(cpg_handle);
return FALSE;
}
gboolean
send_cpg_message(struct iovec * iov)
{
int rc = CS_OK;
int retries = 0;
errno = 0;
do {
rc = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 1);
if (rc == CS_ERR_TRY_AGAIN) {
cpg_flow_control_state_t fc_state = CPG_FLOW_CONTROL_DISABLED;
int rc2 = cpg_flow_control_state_get(cpg_handle, &fc_state);
if (rc2 == CS_OK && fc_state == CPG_FLOW_CONTROL_ENABLED) {
crm_debug("Attempting to clear cpg dispatch queue");
rc2 = cpg_dispatch(cpg_handle, CS_DISPATCH_ALL);
}
if (rc2 != CS_OK) {
crm_warn("Could not check/clear the cpg connection");
goto bail;
} else {
retries++;
crm_debug("Retrying operation after %ds", retries);
sleep(retries);
}
}
/* 5 retires is plenty, we'll resend once the membership reforms anyway */
} while (rc == CS_ERR_TRY_AGAIN && retries < 5);
bail:
if (rc != CS_OK) {
crm_err("Sending message via cpg FAILED: (rc=%d) %s", rc, ais_error2text(rc));
}
return (rc == CS_OK);
}
/* =::=::=::= 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) {
crm_free(*value);
*value = NULL;
}
if (object_handle > 0) {
if (CS_OK == confdb_key_get(config, object_handle, key, strlen(key), &buffer, &len)) {
*value = crm_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);
crm_free(env_key);
if (*value) {
crm_info("Found '%s' in ENV for option: %s", *value, key);
*value = crm_strdup(env_value);
return 0;
}
if (fallback) {
crm_info("Defaulting to '%s' for option: %s", fallback, key);
*value = crm_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(cmap_handle_t object_handle, const char *key, char **value, const char *fallback)
{
int rc = cmap_get_string(object_handle, key, value);
if(rc != CS_OK) {
if(fallback) {
*value = crm_strdup(fallback);
} else {
*value = NULL;
}
}
return rc;
}
#endif
char *
get_local_node_name(void)
{
char *name = NULL;
struct utsname res;
if (use_cman) {
#if SUPPORT_CMAN
cman_node_t us;
cman_handle_t cman;
cman = cman_init(NULL);
if (cman != NULL && cman_is_active(cman)) {
us.cn_name[0] = 0;
cman_get_node(cman, CMAN_NODEID_US, &us);
name = crm_strdup(us.cn_name);
crm_info("Using CMAN node name: %s", name);
} else {
crm_err("Couldn't determin node name from CMAN");
}
cman_finish(cman);
#endif
} else if (uname(&res) < 0) {
crm_perror(LOG_ERR, "Could not determin the current host");
exit(100);
} else {
name = crm_strdup(res.nodename);
}
return name;
}
gboolean
read_config(void)
{
int rc = CS_OK;
gboolean have_log = FALSE;
char *logging_debug = NULL;
char *logging_logfile = NULL;
char *logging_to_logfile = NULL;
char *logging_to_syslog = NULL;
char *logging_syslog_facility = NULL;
enum cluster_type_e stack = get_cluster_type();
#if HAVE_CONFDB
char *value = NULL;
confdb_handle_t config;
confdb_handle_t top_handle = 0;
hdb_handle_t local_handle;
static confdb_callbacks_t callbacks = { };
rc = confdb_initialize(&config, &callbacks);
#endif
#if HAVE_CMAP
cmap_handle_t local_handle;
/* There can be only one (possibility if confdb isn't around) */
rc = cmap_initialize(&local_handle);
#endif
if (rc != CS_OK) {
printf("Could not initialize Cluster Configuration Database API instance, error %d\n", rc);
return FALSE;
}
crm_info("Reading configure for stack: %s", name_for_cluster_type(stack));
/* =::=::= Should we be here =::=::= */
if (stack == pcmk_cluster_corosync) {
setenv("HA_cluster_type", "corosync", 1);
setenv("HA_quorum_type", "corosync", 1);
#if HAVE_CONFDB
} else if (stack == pcmk_cluster_cman) {
setenv("HA_cluster_type", "cman", 1);
setenv("HA_quorum_type", "cman", 1);
enable_crmd_as_root(TRUE);
use_cman = TRUE;
} else if (stack == pcmk_cluster_classic_ais) {
setenv("HA_cluster_type", "openais", 1);
setenv("HA_quorum_type", "pcmk", 1);
/* 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) {
crm_free(value);
get_config_opt(config, local_handle, "name", &value, NULL);
if (safe_str_eq("pacemaker", value)) {
crm_free(value);
get_config_opt(config, local_handle, "ver", &value, "0");
if (safe_str_eq(value, "1")) {
crm_free(value);
get_config_opt(config, local_handle, "use_logd", &value, "no");
setenv("HA_use_logd", value, 1);
crm_free(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.");
exit(100);
}
break;
}
local_handle = config_find_next(config, "service", top_handle);
}
crm_free(value);
#endif
} else {
crm_err("Unsupported stack type: %s", name_for_cluster_type(stack));
return FALSE;
}
#if HAVE_CMAP
/* =::=::= Logging =::=::= */
get_config_opt(local_handle, "logging.debug", &logging_debug, "on");
get_config_opt(local_handle, "logging.logfile", &logging_logfile, "/var/log/pacemaker");
get_config_opt(local_handle, "logging.to_logfile", &logging_to_logfile, "off");
get_config_opt(local_handle, "logging.to_syslog", &logging_to_syslog, "on");
get_config_opt(local_handle, "logging.syslog_facility", &logging_syslog_facility, "daemon");
cmap_finalize(local_handle);
#endif
#if HAVE_CONFDB
top_handle = config_find_init(config);
local_handle = config_find_next(config, "logging", top_handle);
get_config_opt(config, local_handle, "debug", &logging_debug, "on");
get_config_opt(config, local_handle, "logfile", &logging_logfile, "/var/log/pacemaker");
get_config_opt(config, local_handle, "to_logfile", &logging_to_logfile, "off");
get_config_opt(config, local_handle, "to_syslog", &logging_to_syslog, "on");
get_config_opt(config, local_handle, "syslog_facility", &logging_syslog_facility, "daemon");
confdb_finalize(config);
#endif
if (crm_is_true(logging_debug) && get_crm_log_level() < LOG_DEBUG) {
set_crm_log_level(LOG_DEBUG);
}
if (get_crm_log_level() >= LOG_DEBUG) {
setenv("HA_debug", "1", 1);
}
if (crm_is_true(logging_to_logfile)) {
struct stat parent;
uid_t pcmk_uid = 0;
uid_t pcmk_gid = getegid();
FILE *logfile = NULL;
char *parent_dir = NULL;
struct passwd *pcmk_user = getpwnam(CRM_DAEMON_USER);
if(pcmk_user) {
pcmk_uid = pcmk_user->pw_uid;
} else {
crm_err("User %s does not exist. Terminating", CRM_DAEMON_USER);
exit(100);
}
parent_dir = dirname(strdup(logging_logfile));
rc = stat(parent_dir, &parent);
if (rc != 0) {
crm_err("Directory '%s' does not exist for logfile '%s'", parent_dir, logging_logfile);
} else if (parent.st_uid == pcmk_uid && (parent.st_mode & (S_IRUSR | S_IWUSR))) {
/* all good - user */
logfile = fopen(logging_logfile, "a");
} else if (parent.st_gid == pcmk_gid && (parent.st_mode & S_IXGRP)) {
/* all good - group */
logfile = fopen(logging_logfile, "a");
} else {
crm_err
("Daemons running as %s do not have permission to access '%s'. Logging to '%s' is disabled",
CRM_DAEMON_USER, parent_dir, logging_logfile);
}
if (logfile) {
int logfd = fileno(logfile);
setenv("HA_debugfile", logging_logfile, 1);
/* Ensure the file has the correct permissions */
rc = fchown(logfd, pcmk_uid, pcmk_gid);
if(rc < 0) {
crm_warn("Cannot change the ownership of %s to user %s and gid %d",
logging_logfile, 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----", logging_logfile);
}
fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n",
pcmk_uid, pcmk_gid, logging_logfile);
fflush(logfile);
fsync(logfd);
fclose(logfile);
have_log = TRUE;
} else {
crm_err("Couldn't create logfile: %s", logging_logfile);
}
crm_free(parent_dir);
}
if (have_log && crm_is_true(logging_to_syslog) == FALSE) {
crm_info("User configured file based logging and explicitly disabled syslog.");
free(logging_syslog_facility);
logging_syslog_facility = NULL;
} else {
if (crm_is_true(logging_to_syslog) == FALSE) {
crm_err
("Please enable some sort of logging, either 'to_file: on' or 'to_syslog: on'.");
crm_err("If you use file logging, be sure to also define a value for 'logfile'");
}
}
- setenv("HA_logfacility", logging_syslog_facility, 1);
- setenv("HA_LOGFACILITY", logging_syslog_facility, 1);
-
+ if(logging_syslog_facility) {
+ setenv("HA_logfacility", logging_syslog_facility, 1);
+ setenv("HA_LOGFACILITY", logging_syslog_facility, 1);
+ } else {
+ unsetenv("HA_logfacility");
+ unsetenv("HA_LOGFACILITY");
+ }
+
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 75b1594c84..26c3362676 100644
--- a/mcp/pacemaker.sysconfig
+++ b/mcp/pacemaker.sysconfig
@@ -1,14 +1,20 @@
-# Variables for running child daemons under valgrind and/or checking for memory problems
-#export G_SLICE=always-malloc
-#export MALLOC_PERTURB_=221 # or 0
-#export MALLOC_CHECK_=3 # or 0,1,2
-#export PCMK_valgrind_enabled=yes
-#export PCMK_valgrind_enabled=cib,crmd
-#export PCMK_callgrind_enabled=yes
-#export PCMK_callgrind_enabled=cib,crmd
-#export VALGRIND_OPTS="--leak-check=full --trace-children=no --num-callers=25 --log-file=/tmp/pacemaker-%p.valgrind"
+# For non-systemd based systems, prefix export to each enabled line
+
+# 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
# Variables that control logging
-#export PCMK_trace_functions=
-#export PCMK_trace_formats=
-#export PCMK_trace_files=
+# PCMK_trace_functions=function1,function2,function3
+# PCMK_trace_formats="Sent delete %d"
+# PCMK_trace_files=file.c,other.c
+
+# 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=/tmp/pacemaker-%p.valgrind"
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jul 10, 2:05 AM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2009677
Default Alt Text
(21 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment