Example #1
0
int
crm_exit(int rc)
{
    mainloop_cleanup();

#if HAVE_LIBXML2
    crm_trace("cleaning up libxml");
    crm_xml_cleanup();
#endif

    crm_trace("exit %d", rc);
    qb_log_fini();

    free(crm_short_options);
    free(crm_system_name);

    exit(ABS(rc)); /* Always exit with a positive value so that it can be passed to crm_error
                    *
                    * Otherwise the system wraps it around and people
                    * have to jump through hoops figuring out what the
                    * error was
                    */
    return rc;     /* Can never happen, but allows return crm_exit(rc)
                    * where "return rc" was used previously - which
                    * keeps compilers happy.
                    */
}
Example #2
0
crm_exit_t
crm_exit(crm_exit_t rc)
{
    /* A compiler could theoretically use any type for crm_exit_t, but an int
     * should always hold it, so cast to int to keep static analysis happy.
     */
    if ((((int) rc) < 0) || (((int) rc) > CRM_EX_MAX)) {
        rc = CRM_EX_ERROR;
    }

    mainloop_cleanup();
    crm_xml_cleanup();

    qb_log_fini();
    crm_args_fini();

    if (crm_system_name) {
        crm_info("Exiting %s " CRM_XS " with status %d", crm_system_name, rc);
        free(crm_system_name);
    } else {
        crm_trace("Exiting with status %d", rc);
    }

    exit(rc);
    return rc;     /* Can never happen, but allows return crm_exit(rc)
                    * where "return rc" was used previously - which
                    * keeps compilers happy.
                    */
}
Example #3
0
static void sigabrt_handler (int num)
{
	(void)signal (SIGABRT, SIG_DFL);
	qb_log_blackbox_write_to_file(LOCALSTATEDIR "/lib/corosync/fdata");
	qb_log_fini();
	raise (SIGABRT);
}
Example #4
0
END_TEST

#ifdef HAVE_PTHREAD_SETSCHEDPARAM
START_TEST(test_threaded_logging_bad_sched_params)
{
	int32_t t;
	int32_t rc;

	qb_log_init("test", LOG_USER, LOG_EMERG);
	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);

	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
			       QB_LOG_FILTER_FILE, "*", LOG_INFO);
	ck_assert_int_eq(rc, 0);
	qb_log_format_set(t, "%b");
	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
	ck_assert_int_eq(rc, 0);
	rc = qb_log_ctl(t, QB_LOG_CONF_THREADED, QB_TRUE);
	ck_assert_int_eq(rc, 0);

#if defined(SCHED_RR)
#define QB_SCHED SCHED_RR
#elif defined(SCHED_FIFO)
#define QB_SCHED SCHED_FIFO
#else
#define QB_SCHED (-1)
#endif
	rc = qb_log_thread_priority_set(QB_SCHED, -1);
	ck_assert_int_eq(rc, 0);

	rc = qb_log_thread_start();
	ck_assert_int_ne(rc, 0);
	qb_log_fini();
}
Example #5
0
END_TEST

START_TEST(test_log_long_msg)
{
	int lpc;
	int rc;
	int i, max = 1000;
	char *buffer = calloc(1, max);

	qb_log_init("test", LOG_USER, LOG_DEBUG);
	rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
	ck_assert_int_eq(rc, 0);
	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024);
	ck_assert_int_eq(rc, 0);
	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
	ck_assert_int_eq(rc, 0);
	rc = qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
	ck_assert_int_eq(rc, 0);

	for (lpc = 500; lpc < max; lpc++) {
		lpc++;
		for(i = 0; i < max; i++) {
			buffer[i] = 'a' + (i % 10);
		}
		buffer[lpc%600] = 0;
		qb_log(LOG_INFO, "Message %d %d - %s", lpc, lpc%600, buffer);
	}

        qb_log_blackbox_write_to_file("blackbox.dump");
        qb_log_blackbox_print_from_file("blackbox.dump");
	unlink("blackbox.dump");
	qb_log_fini();
}
Example #6
0
static void sigabrt_handler (int num)
{
	(void)signal (SIGABRT, SIG_DFL);
	corosync_blackbox_write_to_file ();
	qb_log_fini();
	raise (SIGABRT);
}
Example #7
0
int
main(int argc, char *argv[])
{
	qb_log_init("linker-contra-log", LOG_USER, LOG_INFO);
	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
	qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
			  QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
	qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);

	qb_log_tags_stringify_fn_set(my_tags_stringify);
	qb_log_format_set(QB_LOG_STDERR, "[%5g|%p] %f:%l:%b");

#if 0
	printf("--\n");
	qb_log_callsites_dump();
	printf("--\n");
#endif

#ifndef NLOG
	qb_log(LOG_INFO, "BEFORE");
#endif
	foo();
#ifndef NLOG
	qb_log(LOG_INFO, "AFTER");
#endif
	qb_log_fini();
}
Example #8
0
static void sigsegv_handler (int num)
{
	(void)signal (SIGSEGV, SIG_DFL);
	corosync_blackbox_write_to_file ();
	qb_log_fini();
	raise (SIGSEGV);
}
Example #9
0
END_TEST
#endif

START_TEST(test_extended_information)
{
	int32_t t;
	int32_t rc;
	int extended;

	qb_log_init("test", LOG_USER, LOG_DEBUG);
	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);

	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
	_ck_assert_int(t, >, QB_LOG_STDOUT);
	qb_log_format_set(t, "%b");
	rc = qb_log_filter_fn_set(NULL);
	ck_assert_int_eq(rc, 0);
	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL, QB_LOG_FILTER_FILE,
			       "*", LOG_TRACE);
	ck_assert_int_eq(rc, 0);
	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL, QB_LOG_FILTER_FORMAT,
			       "*", LOG_TRACE);
	ck_assert_int_eq(rc, 0);
	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FORMAT,
			       "*", LOG_TRACE);
	ck_assert_int_eq(rc, 0);
	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
	ck_assert_int_eq(rc, 0);

	for (extended = QB_FALSE; extended <= QB_TRUE; ++extended) {
		rc = qb_log_ctl(t, QB_LOG_CONF_EXTENDED, extended);
		ck_assert_int_eq(rc, 0);

		num_msgs = 0;

		memset(test_buf, 0, sizeof(test_buf));
		qb_log(LOG_ERR, "message with no extended information");
		ck_assert_str_eq(test_buf, "message with no extended information");

		memset(test_buf, 0, sizeof(test_buf));
		qb_log(LOG_ERR, "message with empty extended information "QB_XS);
		ck_assert_str_eq(test_buf, "message with empty extended information ");

		memset(test_buf, 0, sizeof(test_buf));
		qb_log(LOG_ERR, QB_XS" message with only extended information");
		ck_assert_str_eq(test_buf, extended?
				 "| message with only extended information" : "");

		memset(test_buf, 0, sizeof(test_buf));
		qb_log(LOG_ERR, "message with extended information "QB_XS" (namely this)");
		ck_assert_str_eq(test_buf, extended?
				 "message with extended information | (namely this)"
				 : "message with extended information ");

		ck_assert_int_eq(num_msgs, (extended? 4 : 3));
	}
	qb_log_fini();
}
Example #10
0
END_TEST

START_TEST(test_log_stupid_inputs)
{
	int32_t rc;

	/* shouldn't crash with out an init() */
	qb_log_fini();

	/* not init'ed */
	rc = qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
			       QB_LOG_FILTER_FILE, "bla", LOG_TRACE);
	ck_assert_int_eq(rc, -EINVAL);

	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 2000);
	ck_assert_int_eq(rc, -EINVAL);

	qb_log(LOG_INFO, "not init'd");

	qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
				    __LINE__, 0, "also not init'd");

	qb_log_init("test", LOG_USER, LOG_DEBUG);

	/* non-opened log file */
	rc = qb_log_filter_ctl(21, QB_LOG_FILTER_ADD,
			       QB_LOG_FILTER_FILE, "bla", LOG_TRACE);
	ck_assert_int_eq(rc, -EBADF);

	rc = qb_log_ctl(21, QB_LOG_CONF_PRIORITY_BUMP, -1);
	ck_assert_int_eq(rc, -EBADF);

	/* target < 0 or >= 32 */
	rc = qb_log_filter_ctl(41, QB_LOG_FILTER_ADD,
			       QB_LOG_FILTER_FILE, "bla", LOG_TRACE);
	ck_assert_int_eq(rc, -EBADF);

	rc = qb_log_ctl(-1, QB_LOG_CONF_PRIORITY_BUMP, -1);
	ck_assert_int_eq(rc, -EBADF);

	/* crap values to filter_ctl() */
	rc = qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
			       QB_LOG_FILTER_FILE, NULL, LOG_INFO);
	ck_assert_int_eq(rc, -EINVAL);
	rc = qb_log_filter_ctl(QB_LOG_SYSLOG, 56,
			       QB_LOG_FILTER_FILE, "boja", LOG_INFO);
	ck_assert_int_eq(rc, -EINVAL);

	/* crap values to ctl() */
	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, -2000);
	ck_assert_int_eq(rc, -EINVAL);
	rc = qb_log_ctl(QB_LOG_BLACKBOX, 67, 2000);
	ck_assert_int_eq(rc, -EINVAL);
	rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_SIZE, 2000);
	ck_assert_int_eq(rc, -ENOSYS);

}
Example #11
0
void _corosync_exit_error (
	enum e_ais_done err, const char *file, unsigned int line)
{
	log_printf (LOGSYS_LEVEL_ERROR, "Corosync Cluster Engine exiting "
		"with status %d at %s:%u.\n", err, file, line);

	qb_log_fini();
	exit (err);
}
Example #12
0
static void
sigsegv_handler(int sig)
{
	(void)signal(SIGSEGV, SIG_DFL);
	qb_log_fini();
	if (do_blackbox) {
		qb_log_blackbox_write_to_file("simple-log.fdata");
	}
	raise(SIGSEGV);
}
Example #13
0
void logsys_system_fini (void)
{
	int i;
	int f;
	for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
		free(logsys_loggers[i].logfile);
		for (f = 0; f < logsys_loggers[i].file_idx; f++) {
			free(logsys_loggers[i].files[f]);
		}
	}

	qb_log_fini ();
}
Example #14
0
void
crm_write_blackbox(int nsig)
{
    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 */
            snprintf(buffer, NAME_MAX, "%s.%d", blackbox_file_prefix, counter++);

            if(nsig == 0 && (now - last) < 2) {
                /* Prevent over-dumping */
                return;

            } else if(nsig == SIGTRAP) {
                crm_notice("Blackbox dump requested, please see %s for contents", 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_fini();
            raise(nsig);
            break;
    }
}
Example #15
0
int
crmd_init(void)
{
    int exit_code = 0;
    enum crmd_fsa_state state;

    fsa_state = S_STARTING;
    fsa_input_register = 0;     /* zero out the regester */

    init_dotfile();
    crm_debug("Starting %s", crm_system_name);
    register_fsa_input(C_STARTUP, I_STARTUP, NULL);

    crm_peer_init();
    state = s_crmd_fsa(C_STARTUP);

    if (state == S_PENDING || state == S_STARTING) {
        /* Create the mainloop and run it... */
        crmd_mainloop = g_main_new(FALSE);
        crm_trace("Starting %s's mainloop", crm_system_name);

#ifdef REALTIME_SUPPORT
        static int crm_realtime = 1;

        if (crm_realtime == 1) {
            cl_enable_realtime();
        } else if (crm_realtime == 0) {
            cl_disable_realtime();
        }
        cl_make_realtime(SCHED_RR, 5, 64, 64);
#endif
        g_main_run(crmd_mainloop);
        if (is_set(fsa_input_register, R_STAYDOWN)) {
            crm_info("Inhibiting respawn by Heartbeat");
            exit_code = 100;
        }

    } else {
        crm_err("Startup of %s failed.  Current state: %s",
                crm_system_name, fsa_state2string(state));
        exit_code = 1;
    }

    crm_info("[%s] stopped (%d)", crm_system_name, exit_code);
    qb_log_fini();

    return exit_code;
}
Example #16
0
END_TEST

#ifdef HAVE_SYSLOG_TESTS
START_TEST(test_syslog)
{
	qb_log_init("flip", LOG_USER, LOG_INFO);
	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);

	qb_log(LOG_ERR, "first as flip");
	ck_assert_int_eq(_syslog_opened, 1);
	ck_assert_str_eq(_syslog_ident, "flip");

	qb_log_ctl2(QB_LOG_SYSLOG, QB_LOG_CONF_IDENT, QB_LOG_CTL2_S("flop"));
	qb_log(LOG_ERR, "second as flop");
	ck_assert_str_eq(_syslog_ident, "flop");

	qb_log_fini();
}
Example #17
0
END_TEST

START_TEST(test_threaded_logging)
{
	int32_t t;
	int32_t rc;

	qb_log_init("test", LOG_USER, LOG_EMERG);
	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);

	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
			       QB_LOG_FILTER_FILE, "*", LOG_INFO);
	ck_assert_int_eq(rc, 0);
	qb_log_format_set(t, "%b");
	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
	ck_assert_int_eq(rc, 0);
	rc = qb_log_ctl(t, QB_LOG_CONF_THREADED, QB_TRUE);
	ck_assert_int_eq(rc, 0);
	qb_log_thread_start();

	memset(test_buf, 0, sizeof(test_buf));
	test_priority = 0;
	num_msgs = 0;

	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);

	qb_log_fini();

	ck_assert_int_eq(num_msgs, 10);
}
Example #18
0
void logging_fini(void)
{
	qb_log_fini();
}
Example #19
0
int32_t
main(int32_t argc, char *argv[])
{
	const char *options = "vhteobdf:";
	int32_t opt;
	int32_t tracer;
	int32_t do_stderr = QB_FALSE;
	int32_t do_stdout = QB_FALSE;
	int32_t do_dump_blackbox = QB_FALSE;
	char *logfile = NULL;
	int32_t log_fd = -1;

	while ((opt = getopt(argc, argv, options)) != -1) {
		switch (opt) {
		case 'd':
			do_dump_blackbox = QB_TRUE;
			break;
		case 't':
			do_threaded = QB_TRUE;
			break;
		case 'e':
			do_stderr = QB_TRUE;
			break;
		case 'o':
			do_stdout = QB_TRUE;
			break;
		case 'b':
			do_blackbox = QB_TRUE;
			break;
		case 'f':
			logfile = optarg;
			break;
		case 'v':
			_log_priority++;
			break;
		case 'h':
		default:
			show_usage(argv[0]);
			exit(0);
			break;
		}
	}

	if (do_dump_blackbox) {
		qb_log_blackbox_print_from_file("simple-log.fdata");
		exit(0);
	}

	signal(SIGSEGV, sigsegv_handler);

	qb_log_init("simple-log", LOG_USER, LOG_INFO);
	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, do_threaded);
	qb_log_tags_stringify_fn_set(my_tags_stringify);

	if (do_stderr) {
		qb_log_filter_fn_set(m_filter);
		qb_log_format_set(QB_LOG_STDERR, "[%p] %4g: %f:%l %b");
		qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);

		tracer = qb_log_custom_open(trace_logger, NULL, NULL, NULL);
		qb_log_ctl(tracer, QB_LOG_CONF_ENABLED, QB_TRUE);
		qb_log_format_set(tracer, "%4g: %n() %b");
		qb_log_filter_ctl2(tracer, QB_LOG_FILTER_ADD,
				   QB_LOG_FILTER_FILE, __FILE__,
				   LOG_TRACE, 200);
	}
	if (do_stdout) {
		qb_log_filter_ctl2(QB_LOG_STDOUT, QB_LOG_FILTER_ADD,
				   QB_LOG_FILTER_FILE, __FILE__,
				   LOG_ALERT, QB_MIN(LOG_DEBUG, _log_priority));
		qb_log_format_set(QB_LOG_STDOUT, "[%p] %4g: %f:%l %b");
		qb_log_ctl(QB_LOG_STDOUT, QB_LOG_CONF_ENABLED, QB_TRUE);
	}
	if (do_blackbox) {
		qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
				  QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
		qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 4096);
		qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_THREADED, QB_FALSE);
		qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
	}
	if (logfile) {
		log_fd = qb_log_file_open(logfile);
		qb_log_filter_ctl(log_fd, QB_LOG_FILTER_ADD,
				  QB_LOG_FILTER_FILE, __FILE__, _log_priority);
		qb_log_format_set(log_fd, "[%N] %t %n() [%p] %b");
		qb_log_ctl(log_fd, QB_LOG_CONF_THREADED, do_threaded);
		qb_log_ctl(log_fd, QB_LOG_CONF_ENABLED, QB_TRUE);
	}
	if (do_threaded) {
		qb_log_thread_start();
	}
	qb_log(LOG_DEBUG, "hello");
	qb_log(LOG_INFO, "this is an info");
	qb_log(LOG_NOTICE, "hello - notice?");
	func_one();
	func_two();

	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);

	qb_log(LOG_WARNING, "no syslog");
	qb_log(LOG_ERR, "no syslog");

#if 0
	// test blackbox
	logfile = NULL;
	logfile[5] = 'a';
#endif
	if (do_blackbox) {
		qb_log_blackbox_write_to_file("simple-log.fdata");
		qb_log_blackbox_print_from_file("simple-log.fdata");
		qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
	}
	qb_log_fini();
	return 0;
}
Example #20
0
static void
tengine_stonith_notify(stonith_t * st, stonith_event_t * st_event)
{
    if(te_client_id == NULL) {
        te_client_id = crm_strdup_printf("%s.%d", crm_system_name, getpid());
    }

    if (st_event == NULL) {
        crm_err("Notify data not found");
        return;
    }

    crmd_notify_fencing_op(st_event);

    if (st_event->result == pcmk_ok && safe_str_eq("on", st_event->action)) {
        crm_notice("%s was successfully unfenced by %s (at the request of %s)",
                   st_event->target, st_event->executioner ? st_event->executioner : "<anyone>", st_event->origin);
                /* TODO: Hook up st_event->device */
        return;

    } else if (safe_str_eq("on", st_event->action)) {
        crm_err("Unfencing of %s by %s failed: %s (%d)",
                st_event->target, st_event->executioner ? st_event->executioner : "<anyone>",
                pcmk_strerror(st_event->result), st_event->result);
        return;

    } else if (st_event->result == pcmk_ok && crm_str_eq(st_event->target, fsa_our_uname, TRUE)) {
        crm_crit("We were allegedly just fenced by %s for %s!",
                 st_event->executioner ? st_event->executioner : "<anyone>", st_event->origin); /* Dumps blackbox if enabled */

        qb_log_fini(); /* Try to get the above log message to disk - somehow */

        /* Get out ASAP and do not come back up.
         *
         * Triggering a reboot is also not the worst idea either since
         * the rest of the cluster thinks we're safely down
         */

#ifdef RB_HALT_SYSTEM
        reboot(RB_HALT_SYSTEM);
#endif

        /*
         * If reboot() fails or is not supported, coming back up will
         * probably lead to a situation where the other nodes set our
         * status to 'lost' because of the fencing callback and will
         * discard subsequent election votes with:
         *
         * Election 87 (current: 5171, owner: 103): Processed vote from east-03 (Peer is not part of our cluster)
         *
         * So just stay dead, something is seriously messed up anyway.
         *
         */
        exit(100); /* None of our wrappers since we already called qb_log_fini() */
        return;
    }

    if (st_event->result == pcmk_ok &&
        safe_str_eq(st_event->operation, T_STONITH_NOTIFY_FENCE)) {
        st_fail_count_reset(st_event->target);
    }

    crm_notice("Peer %s was%s terminated (%s) by %s for %s: %s (ref=%s) by client %s",
               st_event->target, st_event->result == pcmk_ok ? "" : " not",
               st_event->action,
               st_event->executioner ? st_event->executioner : "<anyone>",
               st_event->origin, pcmk_strerror(st_event->result), st_event->id,
               st_event->client_origin ? st_event->client_origin : "<unknown>");

#if SUPPORT_CMAN
    if (st_event->result == pcmk_ok && is_cman_cluster()) {
        int local_rc = 0;
        int confirm = 0;
        char *target_copy = strdup(st_event->target);

        /* In case fenced hasn't noticed yet
         *
         * Any fencing that has been inititated will be completed by way of the fence_pcmk redirect
         */
        local_rc = fenced_external(target_copy);
        if (local_rc != 0) {
            crm_err("Could not notify CMAN that '%s' is now fenced: %d", st_event->target,
                    local_rc);
        } else {
            crm_notice("Notified CMAN that '%s' is now fenced", st_event->target);
        }

        /* In case fenced is already trying to shoot it */
        confirm = open("/var/run/cluster/fenced_override", O_NONBLOCK|O_WRONLY);
        if (confirm > 0) {
            int ignore = 0;
            int len = strlen(target_copy);

            errno = 0;
            local_rc = write(confirm, target_copy, len);
            ignore = write(confirm, "\n", 1);

            if(ignore < 0 && errno == EBADF) {
                crm_trace("CMAN not expecting %s to be fenced (yet)", st_event->target);

            } else if (local_rc < len) {
                crm_perror(LOG_ERR, "Confirmation of CMAN fencing event for '%s' failed: %d", st_event->target, local_rc);

            } else {
                fsync(confirm);
                crm_notice("Confirmed CMAN fencing event for '%s'", st_event->target);
            }
            close(confirm);
        }
        free(target_copy);
    }
#endif

    if (st_event->result == pcmk_ok) {
        crm_node_t *peer = crm_find_peer_full(0, st_event->target, CRM_GET_PEER_REMOTE | CRM_GET_PEER_CLUSTER);
        const char *uuid = NULL;
        gboolean we_are_executioner = safe_str_eq(st_event->executioner, fsa_our_uname);

        if (peer == NULL) {
            return;
        }

        uuid = crm_peer_uuid(peer);

        crm_trace("target=%s dc=%s", st_event->target, fsa_our_dc);
        if(AM_I_DC) {
            /* The DC always sends updates */
            send_stonith_update(NULL, st_event->target, uuid);

            if (st_event->client_origin && safe_str_neq(st_event->client_origin, te_client_id)) {

                /* Abort the current transition graph if it wasn't us
                 * that invoked stonith to fence someone
                 */
                crm_info("External fencing operation from %s fenced %s", st_event->client_origin, st_event->target);
                abort_transition(INFINITY, tg_restart, "External Fencing Operation", NULL);
            }

            /* Assume it was our leader if we dont currently have one */
        } else if (fsa_our_dc == NULL || safe_str_eq(fsa_our_dc, st_event->target)) {
            crm_notice("Target %s our leader %s (recorded: %s)",
                       fsa_our_dc ? "was" : "may have been", st_event->target,
                       fsa_our_dc ? fsa_our_dc : "<unset>");

            /* Given the CIB resyncing that occurs around elections,
             * have one node update the CIB now and, if the new DC is different,
             * have them do so too after the election
             */
            if (we_are_executioner) {
                send_stonith_update(NULL, st_event->target, uuid);
            }
            stonith_cleanup_list = g_list_append(stonith_cleanup_list, strdup(st_event->target));

        }

        crmd_peer_down(peer, TRUE);
     }
}
Example #21
0
int main(int argc, char *argv[], char *envp[])
{
	int rv;
	const char *cp;
#ifdef LOGGING_LIBQB
	enum qb_log_target_slot i;
#endif

	init_set_proc_title(argc, argv, envp);
	get_time(&start_time);

	memset(&cl, 0, sizeof(cl));
	strncpy(cl.configfile,
			BOOTH_DEFAULT_CONF, BOOTH_PATH_LEN - 1);
	cl.lockfile[0] = 0;
	debug_level = 0;


	cp = ((cp = strstr(argv[0], ATTR_PROG)) && !strcmp(cp, ATTR_PROG)
		? ATTR_PROG
		: "booth");
#ifndef LOGGING_LIBQB
	cl_log_set_entity(cp);
#else
	qb_log_init(cp, LOG_USER, LOG_DEBUG);  /* prio driven by debug_level */
	for (i = QB_LOG_TARGET_START; i < QB_LOG_TARGET_MAX; i++) {
		if (i == QB_LOG_SYSLOG || i == QB_LOG_BLACKBOX)
			continue;
		qb_log_format_set(i, "%t %H %N: [%P]: %p: %b");
	}
	(void) qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
	                         QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
#endif
	cl_log_enable_stderr(TRUE);
	cl_log_set_facility(0);

	rv = read_arguments(argc, argv);
	if (rv < 0)
		goto out;


	switch (cl.type) {
	case STATUS:
		rv = do_status(cl.type);
		break;

	case ARBITRATOR:
	case DAEMON:
	case SITE:
		rv = do_server(cl.type);
		break;

	case CLIENT:
		rv = do_client();
		break;

	case GEOSTORE:
		rv = do_attr();
		break;
	}

out:
#ifdef LOGGING_LIBQB
	qb_log_fini();
#endif
	/* Normalize values. 0x100 would be seen as "OK" by waitpid(). */
	return (rv >= 0 && rv < 0x70) ? rv : 1;
}
Example #22
0
int
main(int argc, char **argv)
{
    int flag;
    int argerr = 0;
    gboolean allow_cores = TRUE;
    crm_ipc_t *old_instance = NULL;

    crm_system_name = CRM_SYSTEM_PENGINE;
    mainloop_add_signal(SIGTERM, pengine_shutdown);

    while ((flag = getopt(argc, argv, OPTARGS)) != EOF) {
        switch (flag) {
            case 'V':
                crm_bump_log_level();
                break;
            case 'h':          /* Help message */
                usage(crm_system_name, EX_OK);
                break;
            case 'c':
                allow_cores = TRUE;
                break;
            default:
                ++argerr;
                break;
        }
    }

    if (argc - optind == 1 && safe_str_eq("metadata", argv[optind])) {
        pe_metadata();
        return 0;
    }

    if (optind > argc) {
        ++argerr;
    }

    if (argerr) {
        usage(crm_system_name, EX_USAGE);
    }

    crm_log_init(NULL, LOG_NOTICE, TRUE, FALSE, argc, argv, FALSE);

    if (crm_is_writable(PE_STATE_DIR, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) {
        crm_err("Bad permissions on " PE_STATE_DIR ". Terminating");
        fprintf(stderr, "ERROR: Bad permissions on " PE_STATE_DIR ". See logs for details\n");
        fflush(stderr);
        return 100;
    }

    /* find any previous instances and shut them down */
    crm_debug("Checking for old instances of %s", CRM_SYSTEM_PENGINE);
    old_instance = crm_ipc_new(CRM_SYSTEM_PENGINE, 0);
    crm_ipc_connect(old_instance);
    
    crm_debug("Terminating previous instance");
    while (crm_ipc_connected(old_instance)) {
        xmlNode *cmd = create_request(CRM_OP_QUIT, NULL, NULL, CRM_SYSTEM_PENGINE, CRM_SYSTEM_PENGINE, NULL);
        crm_debug(".");
        crm_ipc_send(old_instance, cmd, NULL, 0);
        free_xml(cmd);
        
        sleep(2);
    }
    crm_ipc_close(old_instance);
    crm_ipc_destroy(old_instance);

    crm_debug("Init server comms");
    ipcs = mainloop_add_ipc_server(CRM_SYSTEM_PENGINE, QB_IPC_SHM, &ipc_callbacks);
    if (ipcs == NULL) {
        crm_err("Couldn't start IPC server");
        return 1;
    }

    /* Create the mainloop and run it... */
    crm_info("Starting %s", crm_system_name);

    mainloop = g_main_new(FALSE);
    g_main_run(mainloop);

#if HAVE_LIBXML2
    crm_xml_cleanup();
#endif

    crm_info("Exiting %s", crm_system_name);
    qb_log_fini();
    return 0;
}
Example #23
0
static void
tengine_stonith_notify(stonith_t * st, stonith_event_t * st_event)
{
    if(te_client_id == NULL) {
        te_client_id = crm_strdup_printf("%s.%lu", crm_system_name,
                                         (unsigned long) getpid());
    }

    if (st_event == NULL) {
        crm_err("Notify data not found");
        return;
    }

    crmd_alert_fencing_op(st_event);

    if (st_event->result == pcmk_ok && safe_str_eq("on", st_event->action)) {
        crm_notice("%s was successfully unfenced by %s (at the request of %s)",
                   st_event->target, st_event->executioner ? st_event->executioner : "<anyone>", st_event->origin);
                /* TODO: Hook up st_event->device */
        return;

    } else if (safe_str_eq("on", st_event->action)) {
        crm_err("Unfencing of %s by %s failed: %s (%d)",
                st_event->target, st_event->executioner ? st_event->executioner : "<anyone>",
                pcmk_strerror(st_event->result), st_event->result);
        return;

    } else if (st_event->result == pcmk_ok && crm_str_eq(st_event->target, fsa_our_uname, TRUE)) {
        crm_crit("We were allegedly just fenced by %s for %s!",
                 st_event->executioner ? st_event->executioner : "<anyone>", st_event->origin); /* Dumps blackbox if enabled */

        qb_log_fini(); /* Try to get the above log message to disk - somehow */

        /* Get out ASAP and do not come back up.
         *
         * Triggering a reboot is also not the worst idea either since
         * the rest of the cluster thinks we're safely down
         */

#ifdef RB_HALT_SYSTEM
        reboot(RB_HALT_SYSTEM);
#endif

        /*
         * If reboot() fails or is not supported, coming back up will
         * probably lead to a situation where the other nodes set our
         * status to 'lost' because of the fencing callback and will
         * discard subsequent election votes with:
         *
         * Election 87 (current: 5171, owner: 103): Processed vote from east-03 (Peer is not part of our cluster)
         *
         * So just stay dead, something is seriously messed up anyway.
         *
         */
        exit(CRM_EX_FATAL); // None of our wrappers since we already called qb_log_fini()
        return;
    }

    /* Update the count of stonith failures for this target, in case we become
     * DC later. The current DC has already updated its fail count in
     * tengine_stonith_callback().
     */
    if (!AM_I_DC && safe_str_eq(st_event->operation, T_STONITH_NOTIFY_FENCE)) {
        if (st_event->result == pcmk_ok) {
            st_fail_count_reset(st_event->target);
        } else {
            st_fail_count_increment(st_event->target);
        }
    }

    crm_notice("Peer %s was%s terminated (%s) by %s on behalf of %s: %s "
               CRM_XS " initiator=%s ref=%s",
               st_event->target, st_event->result == pcmk_ok ? "" : " not",
               st_event->action,
               st_event->executioner ? st_event->executioner : "<anyone>",
               (st_event->client_origin? st_event->client_origin : "<unknown>"),
               pcmk_strerror(st_event->result),
               st_event->origin, st_event->id);

    if (st_event->result == pcmk_ok) {
        crm_node_t *peer = crm_find_peer_full(0, st_event->target, CRM_GET_PEER_ANY);
        const char *uuid = NULL;
        gboolean we_are_executioner = safe_str_eq(st_event->executioner, fsa_our_uname);

        if (peer == NULL) {
            return;
        }

        uuid = crm_peer_uuid(peer);

        crm_trace("target=%s dc=%s", st_event->target, fsa_our_dc);
        if(AM_I_DC) {
            /* The DC always sends updates */
            send_stonith_update(NULL, st_event->target, uuid);

            /* @TODO Ideally, at this point, we'd check whether the fenced node
             * hosted any guest nodes, and call remote_node_down() for them.
             * Unfortunately, the controller doesn't have a simple, reliable way
             * to map hosts to guests. It might be possible to track this in the
             * peer cache via crm_remote_peer_cache_refresh(). For now, we rely
             * on the PE creating fence pseudo-events for the guests.
             */

            if (st_event->client_origin && safe_str_neq(st_event->client_origin, te_client_id)) {

                /* Abort the current transition graph if it wasn't us
                 * that invoked stonith to fence someone
                 */
                crm_info("External fencing operation from %s fenced %s", st_event->client_origin, st_event->target);
                abort_transition(INFINITY, tg_restart, "External Fencing Operation", NULL);
            }

            /* Assume it was our leader if we don't currently have one */
        } else if (((fsa_our_dc == NULL) || safe_str_eq(fsa_our_dc, st_event->target))
            && !is_set(peer->flags, crm_remote_node)) {

            crm_notice("Target %s our leader %s (recorded: %s)",
                       fsa_our_dc ? "was" : "may have been", st_event->target,
                       fsa_our_dc ? fsa_our_dc : "<unset>");

            /* Given the CIB resyncing that occurs around elections,
             * have one node update the CIB now and, if the new DC is different,
             * have them do so too after the election
             */
            if (we_are_executioner) {
                send_stonith_update(NULL, st_event->target, uuid);
            }
            add_stonith_cleanup(st_event->target);
        }

        /* If the target is a remote node, and we host its connection,
         * immediately fail all monitors so it can be recovered quickly.
         * The connection won't necessarily drop when a remote node is fenced,
         * so the failure might not otherwise be detected until the next poke.
         */
        if (is_set(peer->flags, crm_remote_node)) {
            remote_ra_fail(st_event->target);
        }

        crmd_peer_down(peer, TRUE);
     }
}
Example #24
0
int
main(int argc, char **argv)
{
    int argerr = 0;
    int flag;
    const char *source = NULL;
    char *admin_input_xml = NULL;
    char *admin_input_file = NULL;
    gboolean dangerous_cmd = FALSE;
    gboolean admin_input_stdin = FALSE;
    xmlNode *output = NULL;
    xmlNode *input = NULL;

    int option_index = 0;

    crm_log_init(NULL, LOG_CRIT, FALSE, FALSE, argc, argv, FALSE);
    crm_set_options(NULL, "command [options] [data]", long_options,
                    "Provides direct access to the cluster configuration."
                    "\n\nAllows the configuration, or sections of it, to be queried, modified, replaced and deleted."
                    "\n\nWhere necessary, XML data will be obtained using the -X, -x, or -p options\n");

    if (argc < 2) {
        crm_help('?', EX_USAGE);
    }

    while (1) {
        flag = crm_get_option(argc, argv, &option_index);
        if (flag == -1)
            break;

        switch (flag) {
            case 't':
                message_timeout_ms = atoi(optarg);
                if (message_timeout_ms < 1) {
                    message_timeout_ms = 30;
                }
                break;
            case 'A':
                obj_type = strdup(optarg);
                command_options |= cib_xpath;
                break;
            case 'u':
                cib_action = CIB_OP_UPGRADE;
                dangerous_cmd = TRUE;
                break;
            case 'E':
                cib_action = CIB_OP_ERASE;
                dangerous_cmd = TRUE;
                break;
            case 'Q':
                cib_action = CIB_OP_QUERY;
                break;
            case 'P':
                cib_action = CIB_OP_APPLY_DIFF;
                break;
            case 'S':
                cib_action = CIB_OP_SYNC;
                break;
            case 'U':
            case 'M':
                cib_action = CIB_OP_MODIFY;
                break;
            case 'R':
                cib_action = CIB_OP_REPLACE;
                break;
            case 'C':
                cib_action = CIB_OP_CREATE;
                break;
            case 'D':
                cib_action = CIB_OP_DELETE;
                break;
            case '5':
                cib_action = "md5-sum";
                break;
            case '6':
                cib_action = "md5-sum-versioned";
                break;
            case 'c':
                command_options |= cib_can_create;
                break;
            case 'n':
                command_options |= cib_no_children;
                break;
            case 'm':
                cib_action = CIB_OP_ISMASTER;
                command_options |= cib_scope_local;
                break;
            case 'B':
                cib_action = CIB_OP_BUMP;
                break;
            case 'r':
                dangerous_cmd = TRUE;
                cib_action = CIB_OP_SLAVE;
                break;
            case 'w':
                dangerous_cmd = TRUE;
                cib_action = CIB_OP_MASTER;
                command_options |= cib_scope_local;
                break;
            case 'V':
                command_options = command_options | cib_verbose;
                crm_bump_log_level(argc, argv);
                break;
            case '?':
            case '$':
            case '!':
                crm_help(flag, EX_OK);
                break;
            case 'o':
                crm_trace("Option %c => %s", flag, optarg);
                obj_type = strdup(optarg);
                break;
            case 'X':
                crm_trace("Option %c => %s", flag, optarg);
                admin_input_xml = strdup(optarg);
                break;
            case 'x':
                crm_trace("Option %c => %s", flag, optarg);
                admin_input_file = strdup(optarg);
                break;
            case 'p':
                admin_input_stdin = TRUE;
                break;
            case 'h':
                host = strdup(optarg);
                break;
            case 'l':
                command_options |= cib_scope_local;
                break;
            case 'd':
                cib_action = CIB_OP_DELETE;
                command_options |= cib_multiple;
                dangerous_cmd = TRUE;
                break;
            case 'b':
                dangerous_cmd = TRUE;
                command_options |= cib_inhibit_bcast;
                command_options |= cib_scope_local;
                break;
            case 's':
                command_options |= cib_sync_call;
                break;
            case 'f':
                force_flag = TRUE;
                command_options |= cib_quorum_override;
                break;
            case 'a':
                output = createEmptyCib();
                crm_xml_add(output, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
                if (optind >= argc) {
                    crm_xml_add(output, XML_ATTR_VALIDATION, LATEST_SCHEMA_VERSION);
                } else {
                    crm_xml_add(output, XML_ATTR_VALIDATION, argv[optind]);
                }
                crm_xml_add_int(output, XML_ATTR_GENERATION_ADMIN, 1);
                crm_xml_add_int(output, XML_ATTR_GENERATION, 0);
                crm_xml_add_int(output, XML_ATTR_NUMUPDATES, 0);

                admin_input_xml = dump_xml_formatted(output);
                fprintf(stdout, "%s\n", crm_str(admin_input_xml));
                goto bail;
                break;
            default:
                printf("Argument code 0%o (%c)" " is not (?yet?) supported\n", flag, flag);
                ++argerr;
                break;
        }
    }

    if (optind < argc) {
        printf("non-option ARGV-elements: ");
        while (optind < argc)
            printf("%s ", argv[optind++]);
        printf("\n");
        crm_help('?', EX_USAGE);
    }

    if (optind > argc || cib_action == NULL) {
        ++argerr;
    }

    if (argerr) {
        crm_help('?', EX_USAGE);
    }

    if (dangerous_cmd && force_flag == FALSE) {
        fprintf(stderr, "The supplied command is considered dangerous."
                "  To prevent accidental destruction of the cluster,"
                " the --force flag is required in order to proceed.\n");
        fflush(stderr);
        exit_code = -EINVAL;
        goto bail;
    }

    if (admin_input_file != NULL) {
        input = filename2xml(admin_input_file);
        source = admin_input_file;

    } else if (admin_input_xml != NULL) {
        source = "input string";
        input = string2xml(admin_input_xml);

    } else if (admin_input_stdin) {
        source = "STDIN";
        input = stdin2xml();
    }

    if (input != NULL) {
        crm_log_xml_debug(input, "[admin input]");

    } else if (source) {
        fprintf(stderr, "Couldn't parse input from %s.\n", source);
        exit_code = -EINVAL;
        goto bail;
    }

    if (safe_str_eq(cib_action, "md5-sum")) {
        char *digest = NULL;

        if (input == NULL) {
            fprintf(stderr, "Please supply XML to process with -X, -x or -p\n");
            exit_code = -EINVAL;
            goto bail;
        }

        digest = calculate_on_disk_digest(input);
        fprintf(stderr, "Digest: ");
        fprintf(stdout, "%s\n", crm_str(digest));
        free(digest);
        goto bail;

    } else if (safe_str_eq(cib_action, "md5-sum-versioned")) {
        char *digest = NULL;
        const char *version = NULL;

        if (input == NULL) {
            fprintf(stderr, "Please supply XML to process with -X, -x or -p\n");
            exit_code = -EINVAL;
            goto bail;
        }

        version = crm_element_value(input, XML_ATTR_CRM_VERSION);
        digest = calculate_xml_versioned_digest(input, FALSE, TRUE, version);
        fprintf(stderr, "Versioned (%s) digest: ", version);
        fprintf(stdout, "%s\n", crm_str(digest));
        free(digest);
        goto bail;
    }
    
    exit_code = do_init();
    if (exit_code != pcmk_ok) {
        crm_err("Init failed, could not perform requested operations");
        fprintf(stderr, "Init failed, could not perform requested operations\n");
        return -exit_code;
    }

    exit_code = do_work(input, command_options, &output);
    if (exit_code > 0) {
        /* wait for the reply by creating a mainloop and running it until
         * the callbacks are invoked...
         */
        request_id = exit_code;

        the_cib->cmds->register_callback(the_cib, request_id, message_timeout_ms, FALSE, NULL,
                                         "cibadmin_op_callback", cibadmin_op_callback);

        mainloop = g_main_new(FALSE);

        crm_trace("%s waiting for reply from the local CIB", crm_system_name);

        crm_info("Starting mainloop");
        g_main_run(mainloop);

    } else if (exit_code < 0) {
        crm_err("Call failed: %s", pcmk_strerror(exit_code));
        fprintf(stderr, "Call failed: %s\n", pcmk_strerror(exit_code));
        operation_status = exit_code;

        if (exit_code == -pcmk_err_dtd_validation) {
            if (crm_str_eq(cib_action, CIB_OP_UPGRADE, TRUE)) {
                xmlNode *obj = NULL;
                int version = 0, rc = 0;

                rc = the_cib->cmds->query(the_cib, NULL, &obj, command_options);
                if (rc == pcmk_ok) {
                    update_validation(&obj, &version, TRUE, FALSE);
                }

            } else if (output) {
                validate_xml_verbose(output);
            }
        }
    }

    if (output != NULL) {
        char *buffer = dump_xml_formatted(output);

        fprintf(stdout, "%s\n", crm_str(buffer));
        free(buffer);
        free_xml(output);
    }

    crm_trace("%s exiting normally", crm_system_name);

    free_xml(input);
    free(admin_input_xml);
    free(admin_input_file);
    the_cib->cmds->signoff(the_cib);
    cib_delete(the_cib);
    crm_xml_cleanup();
  bail:
    qb_log_fini();
    return -exit_code;
}
Example #25
0
int main(int argc, char *argv[])
{
	int ret = -1;
	int lockfd = -1;

	gboolean foreground = FALSE;
	gboolean force_local_mode = FALSE;
	gboolean wrote_pidfile = FALSE;
	memdb_t *memdb = NULL;
	dfsm_t *dcdb = NULL;
	dfsm_t *status_fsm = NULL;

	qb_log_init("pmxcfs", LOG_DAEMON, LOG_DEBUG);
	/* remove default filter */
	qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_REMOVE, 
			  QB_LOG_FILTER_FILE, "*", LOG_DEBUG);

 	qb_log_tags_stringify_fn_set(log_tags_stringify);

	qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);

	update_qb_log_settings();

	g_set_print_handler(glib_print_handler);
	g_set_printerr_handler(glib_print_handler);
	g_log_set_default_handler(glib_log_handler, NULL);

	GOptionContext *context;

	GOptionEntry entries[] = {
		{ "debug", 'd', 0, G_OPTION_ARG_NONE, &cfs.debug, "Turn on debug messages", NULL },
		{ "foreground", 'f', 0, G_OPTION_ARG_NONE, &foreground, "Do not daemonize server", NULL },
		{ "local", 'l', 0, G_OPTION_ARG_NONE, &force_local_mode, 
		  "Force local mode (ignore cluster.conf, force quorum)", NULL },
		{ NULL },
	};

	context = g_option_context_new ("");
	g_option_context_add_main_entries (context, entries, NULL);

	GError *err = NULL;
	if (!g_option_context_parse (context, &argc, &argv, &err))
	{
		cfs_critical("option parsing failed: %s", err->message);
		g_error_free (err);
		qb_log_fini();
		exit (1);
	}
	g_option_context_free(context);

	if (optind < argc) {
		cfs_critical("too many arguments");
		qb_log_fini();
		exit(-1);
	}

	if (cfs.debug) {
		update_qb_log_settings();
	}

	struct utsname utsname;
	if (uname(&utsname) != 0) {
		cfs_critical("Unable to read local node name");
		qb_log_fini();
		exit (-1);
	}
	
	for (int i=0; i < sizeof(utsname.nodename); i++) {
		if (utsname.nodename[i] =='.') utsname.nodename[i] = 0;
	}

	cfs.nodename = g_strdup(utsname.nodename);

	if (!(cfs.ip = lookup_node_ip(cfs.nodename))) { 
		cfs_critical("Unable to get local IP address");
		qb_log_fini();
		exit(-1);
	}

	struct group *www_data = getgrnam("www-data");
	if (!www_data) {
		cfs_critical("Unable to get www-data group ID");
		qb_log_fini();
		exit (-1);
	}
	cfs.gid = www_data->gr_gid;

	g_thread_init(NULL);

	umask(027);

	mkdir(VARLIBDIR, 0755);

	if ((lockfd = open(LOCKFILE, O_RDWR|O_CREAT|O_APPEND)) == -1) {
		cfs_critical("unable to create lock '%s': %s", LOCKFILE, strerror (errno));
		goto err;
	}

	for (int i = 10; i >= 0; i--) {
		if (flock(lockfd, LOCK_EX|LOCK_NB) != 0) {
			if (!i) {
				cfs_critical("unable to aquire pmxcfs lock: %s", strerror (errno));
				goto err;
			}
			if (i == 10)
				cfs_message("unable to aquire pmxcfs lock - trying again");

			sleep(1);
		}
	}

	cfs_status_init();

	gboolean create = !g_file_test(DBFILENAME, G_FILE_TEST_EXISTS);

	if (!(memdb = memdb_open (DBFILENAME))) {
		cfs_critical("memdb_open failed - unable to open database '%s'", DBFILENAME);
		goto err;
	}

	// automatically import cluster.conf from host
	if (create && !force_local_mode) {
		char *cdata = NULL;
		gsize clen = 0;
		if (g_file_get_contents(HOST_CLUSTER_CONF_FN, &cdata, &clen, NULL)) {

			guint32 mtime = time(NULL);

			memdb_create(memdb, "/cluster.conf", 0, mtime);
			if (memdb_write(memdb, "/cluster.conf", 0, mtime, cdata, clen, 0, 1) < 0) {
				cfs_critical("memdb_write failed - unable to import cluster.conf");
				goto err;
			}
		}
	}

	// does cluster.conf exist?
	gpointer conf_data = NULL;
	int len = memdb_read(memdb, "cluster.conf", &conf_data);
	if (len >= 0) {
		if (force_local_mode) {
			cfs_message("forcing local mode (althought cluster.conf exists)");
			cfs_set_quorate(1, TRUE);
		} else {
			if (!(dcdb = dcdb_new(memdb)))
				goto err;
			dcdb_sync_cluster_conf(memdb, 1);
		}
	} else {
		cfs_debug("using local mode (cluster.conf does not exist)");
		cfs_set_quorate(1, TRUE);
	}
	if (conf_data) g_free(conf_data);

	cfs_plug_memdb_t *config = cfs_plug_memdb_new("memdb", memdb, dcdb);
	
	cfs_plug_base_t *bplug = cfs_plug_base_new("", (cfs_plug_t *)config);

	create_symlinks(bplug, cfs.nodename);

	root_plug = (cfs_plug_t *)bplug;

	system("umount -f " CFSDIR " >/dev/null 2>&1");

	char *fa[] = { "-f", "-odefault_permissions", "-oallow_other", NULL};

	struct fuse_args fuse_args = FUSE_ARGS_INIT(sizeof (fa)/sizeof(gpointer) - 1, fa); 
	
	struct fuse_chan *fuse_chan = fuse_mount(CFSDIR, &fuse_args);
	if (!fuse_chan) {
		cfs_critical("fuse_mount error: %s", strerror(errno));
		goto err;
	}

	if (!(fuse = fuse_new(fuse_chan, &fuse_args, &fuse_ops, sizeof(fuse_ops), NULL))) {
		cfs_critical("fuse_new error: %s", strerror(errno));
		goto err;
	}

	fuse_set_signal_handlers(fuse_get_session(fuse));

	if (!foreground) {
		pid_t cpid = fork();

		if (cpid == -1) {
			cfs_critical("failed to daemonize program - %s", strerror (errno));
			goto err;
		} else if (cpid) {
			write_pidfile(cpid);
			qb_log_fini();
			_exit (0);
		} else {
			int nullfd;

			chroot("/");

			if ((nullfd = open("/dev/null", O_RDWR, 0)) != -1) {
				dup2(nullfd, 0);
				dup2(nullfd, 1);
				dup2(nullfd, 2);
				if (nullfd > 2)
					close (nullfd);
			}

			// do not print to the console after this point
			qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);

			setsid();
		}
	} else {
		write_pidfile(getpid());
	}

	wrote_pidfile = TRUE;

	cfs_loop_t *corosync_loop = cfs_loop_new(fuse);

	cfs_service_t *service_quorum = NULL;
	cfs_service_t *service_confdb = NULL;
	cfs_service_t *service_dcdb = NULL;
	cfs_service_t *service_status = NULL;

	if (dcdb) {

		service_quorum = service_quorum_new();

		cfs_loop_add_service(corosync_loop, service_quorum, QB_LOOP_HIGH);

		service_confdb = service_confdb_new();

		cfs_loop_add_service(corosync_loop, service_confdb, QB_LOOP_MED);

		service_dcdb = service_dfsm_new(dcdb);
		cfs_service_set_timer(service_dcdb, DCDB_VERIFY_TIME);

		cfs_loop_add_service(corosync_loop, service_dcdb, QB_LOOP_MED);

		status_fsm = cfs_status_dfsm_new();
		service_status = service_dfsm_new(status_fsm);

		cfs_loop_add_service(corosync_loop, service_status, QB_LOOP_LOW);

	}

	cfs_loop_start_worker(corosync_loop);

	server_start(memdb);

	ret = fuse_loop_mt(fuse);

	cfs_message("teardown filesystem");

	server_stop();

	fuse_unmount(CFSDIR, fuse_chan);

	fuse_destroy(fuse);

	cfs_debug("set stop event loop flag");

	cfs_loop_stop_worker(corosync_loop);

	cfs_loop_destroy(corosync_loop);

	cfs_debug("worker finished");

	if (service_dcdb)
		service_dfsm_destroy(service_dcdb);

	if (service_confdb)
		service_confdb_destroy(service_confdb);

	if (service_quorum)
		service_quorum_destroy(service_quorum);

	if (service_status)
		service_dfsm_destroy(service_status);

	sleep(1); /* do not restart too fast */
 ret:

	if (status_fsm) 
		dfsm_destroy(status_fsm);

	if (dcdb)
		dfsm_destroy(dcdb);

	if (memdb) 
		memdb_close(memdb);

	if (wrote_pidfile)
		unlink(CFS_PID_FN);

	cfs_message("exit proxmox configuration filesystem (%d)", ret);

	cfs_status_cleanup();

	qb_log_fini();

	exit(ret);

 err:
	goto ret;
}