Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/fence/fenced/config.c b/fence/fenced/config.c
index 791150ce1..74c6bdef4 100644
--- a/fence/fenced/config.c
+++ b/fence/fenced/config.c
@@ -1,181 +1,224 @@
#include "fd.h"
#include "config.h"
#include "ccs.h"
static int ccs_handle;
/* was a config value set on command line?, 0 or 1. */
int optd_groupd_compat;
int optd_debug_logsys;
int optd_clean_start;
+int optd_skip_undefined;
int optd_post_join_delay;
int optd_post_fail_delay;
int optd_override_time;
int optd_override_path;
/* actual config value from command line, cluster.conf, or default. */
int cfgd_groupd_compat = DEFAULT_GROUPD_COMPAT;
int cfgd_debug_logsys = DEFAULT_DEBUG_LOGSYS;
int cfgd_clean_start = DEFAULT_CLEAN_START;
+int cfgd_skip_undefined = DEFAULT_SKIP_UNDEFINED;
int cfgd_post_join_delay = DEFAULT_POST_JOIN_DELAY;
int cfgd_post_fail_delay = DEFAULT_POST_FAIL_DELAY;
int cfgd_override_time = DEFAULT_OVERRIDE_TIME;
char *cfgd_override_path = DEFAULT_OVERRIDE_PATH;
int setup_ccs(void)
{
int i = 0, cd;
while ((cd = ccs_connect()) < 0) {
sleep(1);
if (++i > 9 && !(i % 10))
log_error("connect to ccs error %d, "
"check cluster status", cd);
}
ccs_handle = cd;
return 0;
}
void close_ccs(void)
{
ccs_disconnect(ccs_handle);
}
void read_ccs_name(char *path, char *name)
{
char *str;
int error;
error = ccs_get(ccs_handle, path, &str);
if (error || !str)
return;
strcpy(name, str);
free(str);
}
void read_ccs_yesno(char *path, int *yes, int *no)
{
char *str;
int error;
*yes = 0;
*no = 0;
error = ccs_get(ccs_handle, path, &str);
if (error || !str)
return;
if (!strcmp(str, "yes"))
*yes = 1;
else if (!strcmp(str, "no"))
*no = 1;
free(str);
}
void read_ccs_int(char *path, int *config_val)
{
char *str;
int val;
int error;
error = ccs_get(ccs_handle, path, &str);
if (error || !str)
return;
val = atoi(str);
if (val < 0) {
log_error("ignore invalid value %d for %s", val, path);
return;
}
*config_val = val;
log_debug("%s is %u", path, val);
free(str);
}
#define OUR_NAME_PATH "/cluster/clusternodes/clusternode[@name=\"%s\"]/@name"
#define GROUPD_COMPAT_PATH "/cluster/group/@groupd_compat"
#define CLEAN_START_PATH "/cluster/fence_daemon/@clean_start"
#define POST_JOIN_DELAY_PATH "/cluster/fence_daemon/@post_join_delay"
#define POST_FAIL_DELAY_PATH "/cluster/fence_daemon/@post_fail_delay"
#define OVERRIDE_PATH_PATH "/cluster/fence_daemon/@override_path"
#define OVERRIDE_TIME_PATH "/cluster/fence_daemon/@override_time"
+#define METHOD_NAME_PATH "/cluster/clusternodes/clusternode[@name=\"%s\"]/fence/method[%d]/@name"
+
+static int count_methods(char *victim)
+{
+ char path[PATH_MAX], *name;
+ int error, i;
+
+ for (i = 0; i < 2; i++) {
+ memset(path, 0, sizeof(path));
+ sprintf(path, METHOD_NAME_PATH, victim, i+1);
+
+ error = ccs_get(ccs_handle, path, &name);
+ if (error)
+ break;
+ free(name);
+ }
+ return i;
+}
int read_ccs(struct fd *fd)
{
char path[PATH_MAX];
- char *str;
+ char *str, *name;
int error, i = 0, count = 0;
+ int num_methods;
/* Our own nodename must be in cluster.conf before we're allowed to
join the fence domain and then mount gfs; other nodes need this to
fence us. */
str = NULL;
memset(path, 0, sizeof(path));
snprintf(path, sizeof(path), OUR_NAME_PATH, our_name);
error = ccs_get(ccs_handle, path, &str);
if (error || !str) {
log_error("local cman node name \"%s\" not found in the "
"configuration", our_name);
return error;
}
if (str)
free(str);
if (!optd_groupd_compat)
read_ccs_int(GROUPD_COMPAT_PATH, &cfgd_groupd_compat);
if (!optd_clean_start)
read_ccs_int(CLEAN_START_PATH, &cfgd_clean_start);
if (!optd_post_join_delay)
read_ccs_int(POST_JOIN_DELAY_PATH, &cfgd_post_join_delay);
if (!optd_post_fail_delay)
read_ccs_int(POST_FAIL_DELAY_PATH, &cfgd_post_fail_delay);
if (!optd_override_time)
read_ccs_int(OVERRIDE_TIME_PATH, &cfgd_override_time);
if (!optd_override_path) {
str = NULL;
memset(path, 0, sizeof(path));
sprintf(path, OVERRIDE_PATH_PATH);
error = ccs_get(ccs_handle, path, &str);
if (!error && str)
cfgd_override_path = strdup(str);
if (str)
free(str);
}
if (cfgd_clean_start) {
log_debug("clean start, skipping initial nodes");
goto out;
}
for (i = 1; ; i++) {
str = NULL;
memset(path, 0, sizeof(path));
sprintf(path, "/cluster/clusternodes/clusternode[%d]/@nodeid", i);
error = ccs_get(ccs_handle, path, &str);
if (error || !str)
break;
- add_complete_node(fd, atoi(str));
+ name = NULL;
+ memset(path, 0, sizeof(path));
+ sprintf(path, "/cluster/clusternodes/clusternode[%d]/@name", i);
+
+ error = ccs_get(ccs_handle, path, &name);
+ if (error || !name) {
+ log_error("node name query failed for num %d nodeid %s",
+ i, str);
+ break;
+ }
+
+ num_methods = count_methods(name);
+
+ /* the libcpg code only uses the fd->complete list for
+ determining initial victims; the libgroup code uses
+ fd->complete more extensively */
+
+ if (cfgd_skip_undefined && !num_methods)
+ log_debug("skip %s with zero methods", name);
+ else
+ add_complete_node(fd, atoi(str));
+
free(str);
+ free(name);
count++;
}
log_debug("added %d nodes from ccs", count);
out:
return 0;
}
diff --git a/fence/fenced/config.h b/fence/fenced/config.h
index eea8cb6af..c39c7afed 100644
--- a/fence/fenced/config.h
+++ b/fence/fenced/config.h
@@ -1,29 +1,32 @@
#ifndef __CONFIG_DOT_H__
#define __CONFIG_DOT_H__
#define DEFAULT_GROUPD_COMPAT 2
#define DEFAULT_DEBUG_LOGSYS 0
#define DEFAULT_CLEAN_START 0
+#define DEFAULT_SKIP_UNDEFINED 0
#define DEFAULT_POST_JOIN_DELAY 6
#define DEFAULT_POST_FAIL_DELAY 0
#define DEFAULT_OVERRIDE_TIME 3
#define DEFAULT_OVERRIDE_PATH "/var/run/cluster/fenced_override"
extern int optd_groupd_compat;
extern int optd_debug_logsys;
extern int optd_clean_start;
+extern int optd_skip_undefined;
extern int optd_post_join_delay;
extern int optd_post_fail_delay;
extern int optd_override_time;
extern int optd_override_path;
extern int cfgd_groupd_compat;
extern int cfgd_debug_logsys;
extern int cfgd_clean_start;
+extern int cfgd_skip_undefined;
extern int cfgd_post_join_delay;
extern int cfgd_post_fail_delay;
extern int cfgd_override_time;
extern char *cfgd_override_path;
#endif
diff --git a/fence/fenced/main.c b/fence/fenced/main.c
index bc6ee11a9..ae5f66224 100644
--- a/fence/fenced/main.c
+++ b/fence/fenced/main.c
@@ -1,926 +1,932 @@
#include "fd.h"
#include "config.h"
#include <pthread.h>
#include "copyright.cf"
#define LOCKFILE_NAME "/var/run/fenced.pid"
#define CLIENT_NALLOC 32
static int client_maxi;
static int client_size = 0;
static struct client *client = NULL;
static struct pollfd *pollfd = NULL;
static pthread_t query_thread;
static pthread_mutex_t query_mutex;
struct client {
int fd;
void *workfn;
void *deadfn;
};
static int do_read(int fd, void *buf, size_t count)
{
int rv, off = 0;
while (off < count) {
rv = read(fd, buf + off, count - off);
if (rv == 0)
return -1;
if (rv == -1 && errno == EINTR)
continue;
if (rv == -1)
return -1;
off += rv;
}
return 0;
}
static int do_write(int fd, void *buf, size_t count)
{
int rv, off = 0;
retry:
rv = write(fd, buf + off, count);
if (rv == -1 && errno == EINTR)
goto retry;
if (rv < 0) {
return rv;
}
if (rv != count) {
count -= rv;
off += rv;
goto retry;
}
return 0;
}
static void client_alloc(void)
{
int i;
if (!client) {
client = malloc(CLIENT_NALLOC * sizeof(struct client));
pollfd = malloc(CLIENT_NALLOC * sizeof(struct pollfd));
} else {
client = realloc(client, (client_size + CLIENT_NALLOC) *
sizeof(struct client));
pollfd = realloc(pollfd, (client_size + CLIENT_NALLOC) *
sizeof(struct pollfd));
if (!pollfd)
log_error("can't alloc for pollfd");
}
if (!client || !pollfd)
log_error("can't alloc for client array");
for (i = client_size; i < client_size + CLIENT_NALLOC; i++) {
client[i].workfn = NULL;
client[i].deadfn = NULL;
client[i].fd = -1;
pollfd[i].fd = -1;
pollfd[i].revents = 0;
}
client_size += CLIENT_NALLOC;
}
void client_dead(int ci)
{
close(client[ci].fd);
client[ci].workfn = NULL;
client[ci].fd = -1;
pollfd[ci].fd = -1;
}
int client_add(int fd, void (*workfn)(int ci), void (*deadfn)(int ci))
{
int i;
if (!client)
client_alloc();
again:
for (i = 0; i < client_size; i++) {
if (client[i].fd == -1) {
client[i].workfn = workfn;
if (deadfn)
client[i].deadfn = deadfn;
else
client[i].deadfn = client_dead;
client[i].fd = fd;
pollfd[i].fd = fd;
pollfd[i].events = POLLIN;
if (i > client_maxi)
client_maxi = i;
return i;
}
}
client_alloc();
goto again;
}
static void sigterm_handler(int sig)
{
daemon_quit = 1;
}
static struct fd *create_fd(char *name)
{
struct fd *fd;
if (strlen(name) > MAX_GROUPNAME_LEN)
return NULL;
fd = malloc(sizeof(struct fd));
if (!fd)
return NULL;
memset(fd, 0, sizeof(struct fd));
strcpy(fd->name, name);
INIT_LIST_HEAD(&fd->changes);
INIT_LIST_HEAD(&fd->node_history);
INIT_LIST_HEAD(&fd->victims);
INIT_LIST_HEAD(&fd->complete);
INIT_LIST_HEAD(&fd->prev);
INIT_LIST_HEAD(&fd->leaving);
return fd;
}
void free_fd(struct fd *fd)
{
struct change *cg, *cg_safe;
struct node_history *nodeh, *nodeh_safe;
list_for_each_entry_safe(cg, cg_safe, &fd->changes, list) {
list_del(&cg->list);
free_cg(cg);
}
if (fd->started_change)
free_cg(fd->started_change);
list_for_each_entry_safe(nodeh, nodeh_safe, &fd->node_history, list) {
list_del(&nodeh->list);
free(nodeh);
}
free_node_list(&fd->victims);
free_node_list(&fd->complete);
free_node_list(&fd->prev);
free_node_list(&fd->leaving);
free(fd);
}
struct fd *find_fd(char *name)
{
struct fd *fd;
list_for_each_entry(fd, &domains, list) {
if (strlen(name) == strlen(fd->name) &&
!strncmp(fd->name, name, strlen(name)))
return fd;
}
return NULL;
}
static int do_join(char *name)
{
struct fd *fd;
int rv;
fd = find_fd(name);
if (fd) {
log_debug("join error: domain %s exists", name);
rv = -EEXIST;
goto out;
}
fd = create_fd(name);
if (!fd) {
rv = -ENOMEM;
goto out;
}
rv = read_ccs(fd);
if (rv) {
free(fd);
goto out;
}
if (group_mode == GROUP_LIBGROUP)
rv = fd_join_group(fd);
else
rv = fd_join(fd);
out:
return rv;
}
static int do_leave(char *name)
{
struct fd *fd;
int rv;
fd = find_fd(name);
if (!fd)
return -EINVAL;
if (group_mode == GROUP_LIBGROUP)
rv = fd_leave_group(fd);
else
rv = fd_leave(fd);
return rv;
}
static int do_external(char *name, char *extra, int extra_len)
{
struct fd *fd;
int rv = 0;
fd = find_fd(name);
if (!fd)
return -EINVAL;
if (group_mode == GROUP_LIBGROUP)
rv = -ENOSYS;
else
send_external(fd, name_to_nodeid(extra));
return rv;
}
static void init_header(struct fenced_header *h, int cmd, int result,
int extra_len)
{
memset(h, 0, sizeof(struct fenced_header));
h->magic = FENCED_MAGIC;
h->version = FENCED_VERSION;
h->len = sizeof(struct fenced_header) + extra_len;
h->command = cmd;
h->data = result;
}
/* combines a header and the data and sends it back to the client in
a single do_write() call */
static void do_reply(int f, int cmd, int result, char *buf, int buflen)
{
char *reply;
int reply_len;
reply_len = sizeof(struct fenced_header) + buflen;
reply = malloc(reply_len);
if (!reply)
return;
memset(reply, 0, reply_len);
init_header((struct fenced_header *)reply, cmd, result, buflen);
if (buf && buflen)
memcpy(reply + sizeof(struct fenced_header), buf, buflen);
do_write(f, reply, reply_len);
free(reply);
}
static void query_dump_debug(int f)
{
struct fenced_header h;
int extra_len;
int len;
/* in the case of dump_wrap, extra_len will go in two writes,
first the log tail, then the log head */
if (dump_wrap)
extra_len = FENCED_DUMP_SIZE;
else
extra_len = dump_point;
init_header(&h, FENCED_CMD_DUMP_DEBUG, 0, extra_len);
do_write(f, &h, sizeof(h));
if (dump_wrap) {
len = FENCED_DUMP_SIZE - dump_point;
do_write(f, dump_buf + dump_point, len);
len = dump_point;
} else
len = dump_point;
/* NUL terminate the debug string */
dump_buf[dump_point] = '\0';
do_write(f, dump_buf, len);
}
static void query_node_info(int f, int data_nodeid)
{
struct fd *fd;
struct fenced_node node;
int nodeid, rv;
fd = find_fd("default");
if (!fd) {
rv = -ENOENT;
goto out;
}
if (data_nodeid == FENCED_NODEID_US)
nodeid = our_nodeid;
else
nodeid = data_nodeid;
if (group_mode == GROUP_LIBGROUP)
rv = set_node_info_group(fd, nodeid, &node);
else
rv = set_node_info(fd, nodeid, &node);
out:
do_reply(f, FENCED_CMD_NODE_INFO, rv, (char *)&node, sizeof(node));
}
static void query_domain_info(int f)
{
struct fd *fd;
struct fenced_domain domain;
int rv;
fd = find_fd("default");
if (!fd) {
rv = -ENOENT;
goto out;
}
memset(&domain, 0, sizeof(domain));
domain.group_mode = group_mode;
if (group_mode == GROUP_LIBGROUP)
rv = set_domain_info_group(fd, &domain);
else
rv = set_domain_info(fd, &domain);
out:
do_reply(f, FENCED_CMD_DOMAIN_INFO, rv, (char *)&domain, sizeof(domain));
}
static void query_domain_nodes(int f, int option, int max)
{
struct fd *fd;
int node_count = 0;
struct fenced_node *nodes = NULL;
int rv, result;
fd = find_fd("default");
if (!fd) {
result = -ENOENT;
node_count = 0;
goto out;
}
if (group_mode == GROUP_LIBGROUP)
rv = set_domain_nodes_group(fd, option, &node_count, &nodes);
else
rv = set_domain_nodes(fd, option, &node_count, &nodes);
if (rv < 0) {
result = rv;
node_count = 0;
goto out;
}
/* node_count is the number of structs copied/returned; the caller's
max may be less than that, in which case we copy as many as they
asked for and return -E2BIG */
if (node_count > max) {
result = -E2BIG;
node_count = max;
} else {
result = node_count;
}
out:
do_reply(f, FENCED_CMD_DOMAIN_NODES, result,
(char *)nodes, node_count * sizeof(struct fenced_node));
if (nodes)
free(nodes);
}
static void process_connection(int ci)
{
struct fenced_header h;
char *extra = NULL;
int rv, extra_len;
rv = do_read(client[ci].fd, &h, sizeof(h));
if (rv < 0) {
log_debug("connection %d read error %d", ci, rv);
goto out;
}
if (h.magic != FENCED_MAGIC) {
log_debug("connection %d magic error %x", ci, h.magic);
goto out;
}
if ((h.version & 0xFFFF0000) != (FENCED_VERSION & 0xFFFF0000)) {
log_debug("connection %d version error %x", ci, h.version);
goto out;
}
if (h.len > sizeof(h)) {
extra_len = h.len - sizeof(h);
extra = malloc(extra_len);
if (!extra) {
log_error("process_connection no mem %d", extra_len);
goto out;
}
memset(extra, 0, extra_len);
rv = do_read(client[ci].fd, extra, extra_len);
if (rv < 0) {
log_debug("connection %d extra read error %d", ci, rv);
goto out;
}
}
switch (h.command) {
case FENCED_CMD_JOIN:
do_join("default");
break;
case FENCED_CMD_LEAVE:
do_leave("default");
break;
case FENCED_CMD_EXTERNAL:
do_external("default", extra, extra_len);
break;
case FENCED_CMD_DUMP_DEBUG:
case FENCED_CMD_NODE_INFO:
case FENCED_CMD_DOMAIN_INFO:
case FENCED_CMD_DOMAIN_NODES:
log_error("process_connection query on wrong socket");
break;
default:
log_error("process_connection %d unknown command %d",
ci, h.command);
}
out:
if (extra)
free(extra);
client_dead(ci);
}
static void process_listener(int ci)
{
int fd, i;
fd = accept(client[ci].fd, NULL, NULL);
if (fd < 0) {
log_error("process_listener: accept error %d %d", fd, errno);
return;
}
i = client_add(fd, process_connection, NULL);
log_debug("client connection %d fd %d", i, fd);
}
static int setup_listener(char *sock_path)
{
struct sockaddr_un addr;
socklen_t addrlen;
int rv, s;
/* we listen for new client connections on socket s */
s = socket(AF_LOCAL, SOCK_STREAM, 0);
if (s < 0) {
log_error("socket error %d %d", s, errno);
return s;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_LOCAL;
strcpy(&addr.sun_path[1], sock_path);
addrlen = sizeof(sa_family_t) + strlen(addr.sun_path+1) + 1;
rv = bind(s, (struct sockaddr *) &addr, addrlen);
if (rv < 0) {
log_error("bind error %d %d", rv, errno);
close(s);
return rv;
}
rv = listen(s, 5);
if (rv < 0) {
log_error("listen error %d %d", rv, errno);
close(s);
return rv;
}
return s;
}
void query_lock(void)
{
pthread_mutex_lock(&query_mutex);
}
void query_unlock(void)
{
pthread_mutex_unlock(&query_mutex);
}
/* This is a thread, so we have to be careful, don't call log_ functions.
We need a thread to process queries because the main thread will block
for long periods when running fence agents. */
static void *process_queries(void *arg)
{
struct fenced_header h;
int s = *((int *)arg);
int f, rv;
for (;;) {
f = accept(s, NULL, NULL);
rv = do_read(f, &h, sizeof(h));
if (rv < 0) {
goto out;
}
if (h.magic != FENCED_MAGIC) {
goto out;
}
if ((h.version & 0xFFFF0000) != (FENCED_VERSION & 0xFFFF0000)) {
goto out;
}
pthread_mutex_lock(&query_mutex);
switch (h.command) {
case FENCED_CMD_DUMP_DEBUG:
query_dump_debug(f);
break;
case FENCED_CMD_NODE_INFO:
query_node_info(f, h.data);
break;
case FENCED_CMD_DOMAIN_INFO:
query_domain_info(f);
break;
case FENCED_CMD_DOMAIN_NODES:
query_domain_nodes(f, h.option, h.data);
break;
default:
break;
}
pthread_mutex_unlock(&query_mutex);
out:
close(f);
}
}
static int setup_queries(void)
{
int rv, s;
rv = setup_listener(FENCED_QUERY_SOCK_PATH);
if (rv < 0)
return rv;
s = rv;
pthread_mutex_init(&query_mutex, NULL);
rv = pthread_create(&query_thread, NULL, process_queries, &s);
if (rv < 0) {
log_error("can't create query thread");
close(s);
return rv;
}
return 0;
}
void cluster_dead(int ci)
{
log_error("cluster is down, exiting");
daemon_quit = 1;
}
static void loop(void)
{
int rv, i;
void (*workfn) (int ci);
void (*deadfn) (int ci);
rv = setup_queries();
if (rv < 0)
goto out;
rv = setup_listener(FENCED_SOCK_PATH);
if (rv < 0)
goto out;
client_add(rv, process_listener, NULL);
rv = setup_cman();
if (rv < 0)
goto out;
client_add(rv, process_cman, cluster_dead);
rv = setup_ccs();
if (rv < 0)
goto out;
setup_logging();
group_mode = GROUP_LIBCPG;
if (cfgd_groupd_compat) {
rv = setup_groupd();
if (rv < 0)
goto out;
client_add(rv, process_groupd, cluster_dead);
group_mode = GROUP_LIBGROUP;
if (cfgd_groupd_compat == 2)
set_group_mode();
}
log_debug("group_mode %d compat %d", group_mode, cfgd_groupd_compat);
if (group_mode == GROUP_LIBCPG) {
/*
rv = setup_cpg();
if (rv < 0)
goto out;
client_add(rv, process_cpg, cluster_dead);
*/
}
for (;;) {
rv = poll(pollfd, client_maxi + 1, -1);
if (rv == -1 && errno == EINTR) {
if (daemon_quit && list_empty(&domains))
goto out;
daemon_quit = 0;
continue;
}
if (rv < 0) {
log_error("poll errno %d", errno);
goto out;
}
pthread_mutex_lock(&query_mutex);
for (i = 0; i <= client_maxi; i++) {
if (client[i].fd < 0)
continue;
if (pollfd[i].revents & POLLIN) {
workfn = client[i].workfn;
workfn(i);
}
if (pollfd[i].revents & (POLLERR | POLLHUP | POLLNVAL)) {
deadfn = client[i].deadfn;
deadfn(i);
}
}
pthread_mutex_unlock(&query_mutex);
if (daemon_quit)
break;
}
out:
if (cfgd_groupd_compat)
close_groupd();
close_logging();
close_ccs();
close_cman();
if (!list_empty(&domains))
log_error("domain abandoned");
}
static void lockfile(void)
{
int fd, error;
struct flock lock;
char buf[33];
memset(buf, 0, 33);
fd = open(LOCKFILE_NAME, O_CREAT|O_WRONLY,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd < 0) {
fprintf(stderr, "cannot open/create lock file %s\n",
LOCKFILE_NAME);
exit(EXIT_FAILURE);
}
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
error = fcntl(fd, F_SETLK, &lock);
if (error) {
fprintf(stderr, "is already running\n");
exit(EXIT_FAILURE);
}
error = ftruncate(fd, 0);
if (error) {
fprintf(stderr, "cannot clear lock file %s\n", LOCKFILE_NAME);
exit(EXIT_FAILURE);
}
sprintf(buf, "%d\n", getpid());
error = write(fd, buf, strlen(buf));
if (error <= 0) {
fprintf(stderr, "cannot write lock file %s\n", LOCKFILE_NAME);
exit(EXIT_FAILURE);
}
}
static void print_usage(void)
{
printf("Usage:\n");
printf("\n");
printf("fenced [options]\n");
printf("\n");
printf("Options:\n");
printf("\n");
printf(" -D Enable debugging code and don't fork\n");
printf(" -L <num> Enable (1) or disable (0) debugging to logsys (default %d)\n", DEFAULT_DEBUG_LOGSYS);
printf(" -g <num> groupd compatibility mode, 0 off, 1 on, 2 detect (default %d)\n", DEFAULT_GROUPD_COMPAT);
printf(" 0: use libcpg, no backward compat, best performance\n");
printf(" 1: use libgroup for compat with cluster2/rhel5\n");
printf(" 2: use groupd to detect old, or mode 1, nodes that\n"
" require compat, use libcpg if none found\n");
printf(" -c All nodes are in a clean state to start\n");
+ printf(" -s Skip startup fencing of nodes with no defined fence methods\n");
printf(" -j <secs> Post-join fencing delay (default %d)\n", DEFAULT_POST_JOIN_DELAY);
printf(" -f <secs> Post-fail fencing delay (default %d)\n", DEFAULT_POST_FAIL_DELAY);
printf(" -R <secs> Override time (default %d)\n", DEFAULT_OVERRIDE_TIME);
printf(" -O <path> Override path (default %s)\n", DEFAULT_OVERRIDE_PATH);
printf(" -h Print this help, then exit\n");
printf(" -V Print program version information, then exit\n");
printf("\n");
printf("Command line values override those in " DEFAULT_CONFIG_DIR "/" DEFAULT_CONFIG_FILE ".\n");
printf("For an unbounded delay use <secs> value of -1.\n");
printf("\n");
}
-#define OPTION_STRING "L:g:cj:f:Dn:O:T:hVS"
+#define OPTION_STRING "L:g:cj:f:Dn:O:hVSs"
static void read_arguments(int argc, char **argv)
{
int cont = 1;
int optchar;
while (cont) {
optchar = getopt(argc, argv, OPTION_STRING);
switch (optchar) {
case 'D':
daemon_debug_opt = 1;
break;
case 'L':
optd_debug_logsys = 1;
cfgd_debug_logsys = atoi(optarg);
break;
case 'g':
optd_groupd_compat = 1;
cfgd_groupd_compat = atoi(optarg);
break;
case 'c':
optd_clean_start = 1;
cfgd_clean_start = 1;
break;
+ case 's':
+ optd_skip_undefined = 1;
+ cfgd_skip_undefined = 1;
+ break;
+
case 'j':
optd_post_join_delay = 1;
cfgd_post_join_delay = atoi(optarg);
break;
case 'f':
optd_post_fail_delay = 1;
cfgd_post_fail_delay = atoi(optarg);
break;
case 'R':
optd_override_time = 1;
cfgd_override_time = atoi(optarg);
if (cfgd_override_time < 3)
cfgd_override_time = 3;
break;
case 'O':
optd_override_path = 1;
cfgd_override_path = strdup(optarg);
break;
case 'h':
print_usage();
exit(EXIT_SUCCESS);
break;
case 'V':
printf("fenced %s (built %s %s)\n", RELEASE_VERSION,
__DATE__, __TIME__);
printf("%s\n", REDHAT_COPYRIGHT);
exit(EXIT_SUCCESS);
break;
case ':':
case '?':
fprintf(stderr, "Please use '-h' for usage.\n");
exit(EXIT_FAILURE);
break;
case EOF:
cont = 0;
break;
default:
fprintf(stderr, "unknown option: %c", optchar);
exit(EXIT_FAILURE);
};
}
if (!optd_debug_logsys && getenv("FENCED_DEBUG")) {
optd_debug_logsys = 1;
cfgd_debug_logsys = atoi(getenv("FENCED_DEBUG"));
}
}
static void set_oom_adj(int val)
{
FILE *fp;
fp = fopen("/proc/self/oom_adj", "w");
if (!fp)
return;
fprintf(fp, "%i", val);
fclose(fp);
}
int main(int argc, char **argv)
{
INIT_LIST_HEAD(&domains);
init_logging();
read_arguments(argc, argv);
lockfile();
if (!daemon_debug_opt) {
if (daemon(0, 0) < 0) {
perror("main: cannot fork");
exit(EXIT_FAILURE);
}
umask(0);
}
signal(SIGTERM, sigterm_handler);
set_oom_adj(-16);
loop();
return 0;
}
void daemon_dump_save(void)
{
int len, i;
len = strlen(daemon_debug_buf);
for (i = 0; i < len; i++) {
dump_buf[dump_point++] = daemon_debug_buf[i];
if (dump_point == FENCED_DUMP_SIZE) {
dump_point = 0;
dump_wrap = 1;
}
}
}
int daemon_debug_opt;
int daemon_quit;
struct list_head domains;
int cman_quorate;
int our_nodeid;
char our_name[MAX_NODENAME_LEN+1];
char daemon_debug_buf[256];
char dump_buf[FENCED_DUMP_SIZE];
int dump_point;
int dump_wrap;
int group_mode;

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 23, 11:04 AM (1 d, 12 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018606
Default Alt Text
(25 KB)

Event Timeline