Ejemplo n.º 1
0
int join(commandline_t *comline, char *main_envp[])
{
	int i, err;
	int envptr = 0;
	int argvptr = 0;
	char scratch[1024];
	char config_modules[1024];
	cman_handle_t h = NULL;
	int status;
	hdb_handle_t object_handle;
	confdb_handle_t confdb_handle;
	int res;
	pid_t corosync_pid;
	int p[2];
	confdb_callbacks_t callbacks = {
		.confdb_key_change_notify_fn = NULL,
		.confdb_object_create_change_notify_fn = NULL,
		.confdb_object_delete_change_notify_fn = NULL
	};

        /*
	 * If we can talk to cman then we're already joined (or joining);
	 */
	h = cman_admin_init(NULL);
	if (h)
		die("Node is already active");

	/* Set up environment variables for override */
	if (comline->multicast_addr) {
		snprintf(scratch, sizeof(scratch), "CMAN_MCAST_ADDR=%s", comline->multicast_addr);
		envp[envptr++] = strdup(scratch);
	}
	if (comline->votes_opt) {
		snprintf(scratch, sizeof(scratch), "CMAN_VOTES=%d", comline->votes);
		envp[envptr++] = strdup(scratch);
	}
	if (comline->expected_votes_opt) {
		snprintf(scratch, sizeof(scratch), "CMAN_EXPECTEDVOTES=%d", comline->expected_votes);
		envp[envptr++] = strdup(scratch);
	}
	if (comline->port) {
		snprintf(scratch, sizeof(scratch), "CMAN_IP_PORT=%d", comline->port);
		envp[envptr++] = strdup(scratch);
	}
	if (comline->nodeid) {
		snprintf(scratch, sizeof(scratch), "CMAN_NODEID=%d", comline->nodeid);
		envp[envptr++] = strdup(scratch);
	}
	if (comline->clustername_opt) {
		snprintf(scratch, sizeof(scratch), "CMAN_CLUSTER_NAME=%s", comline->clustername);
		envp[envptr++] = strdup(scratch);
	}
	if (comline->nodenames[0]) {
		snprintf(scratch, sizeof(scratch), "CMAN_NODENAME=%s", comline->nodenames[0]);
		envp[envptr++] = strdup(scratch);
	}
	if (comline->key_filename) {
		snprintf(scratch, sizeof(scratch), "CMAN_KEYFILE=%s", comline->key_filename);
		envp[envptr++] = strdup(scratch);
	}
	if (comline->two_node) {
		snprintf(scratch, sizeof(scratch), "CMAN_2NODE=true");
		envp[envptr++] = strdup(scratch);
	}
	if (comline->verbose ^ DEBUG_STARTUP_ONLY) {
		snprintf(scratch, sizeof(scratch), "CMAN_DEBUG=%d", comline->verbose);
		envp[envptr++] = strdup(scratch);
	}
	if (comline->nostderr_debug) {
		snprintf(scratch, sizeof(scratch), "CMAN_NOSTDERR_DEBUG=true");
		envp[envptr++] = strdup(scratch);
	}
	if (comline->noconfig_opt) {
		envp[envptr++] = strdup("CMAN_NOCONFIG=true");
		snprintf(config_modules, sizeof(config_modules), "cmanpreconfig");
	}
	else {
		snprintf(config_modules, sizeof(config_modules), "%s:cmanpreconfig", comline->config_lcrso);
	}
	if (comline->noopenais_opt) {
		envp[envptr++] = strdup("CMAN_NOOPENAIS=true");
	}

	snprintf(scratch, sizeof(scratch), "COROSYNC_DEFAULT_CONFIG_IFACE=%s", config_modules);
	envp[envptr++] = strdup(scratch);

	/* Copy any COROSYNC_* env variables to the new daemon */
	i=0;
	while (i < MAX_ARGS && main_envp[i]) {
		if (strncmp(main_envp[i], "COROSYNC_", 9) == 0)
			envp[envptr++] = main_envp[i];
		i++;
	}


	/* Create a pipe to monitor cman startup progress */
	if (pipe(p) < 0)
		die("unable to create pipe: %s", strerror(errno));
	fcntl(p[1], F_SETFD, 0); /* Don't close on exec */
	snprintf(scratch, sizeof(scratch), "CMAN_PIPE=%d", p[1]);
	envp[envptr++] = strdup(scratch);
	envp[envptr++] = NULL;

	/* Always run corosync -f because we have already forked twice anyway, and
	   we want to return any exit code that might happen */
	/* also strdup strings because it's otherwise virtually impossible to fix
	 * build warnings due to the way argv C implementation is done */
	argv[0] = strdup("corosync");
	argv[++argvptr] = strdup("-f");
	if (comline->nosetpri_opt)
		argv[++argvptr] = strdup("-p");
	argv[++argvptr] = NULL;

	/* Fork/exec cman */
	switch ( (corosync_pid = fork()) )
	{
	case -1:
		die("fork of corosync daemon failed: %s", strerror(errno));

	case 0: /* child */
		close(p[0]);
		if (comline->verbose & DEBUG_STARTUP_ONLY) {
			fprintf(stderr, "Starting %s", COROSYNCBIN);
			for (i=0; i< argvptr; i++) {
				fprintf(stderr, " %s", argv[i]);
			}
			fprintf(stderr, "\n");
			for (i=0; i<envptr-1; i++) {
				fprintf(stderr, "%s\n", envp[i]);
			}
		}
		be_daemon();

		sprintf(scratch, "FORKED: %d\n", getpid());
		err = write(p[1], scratch, strlen(scratch));

		execve(COROSYNCBIN, argv, envp);

		/* exec failed - tell the parent process */
		sprintf(scratch, "execve of " COROSYNCBIN " failed: %s", strerror(errno));
		err = write(p[1], scratch, strlen(scratch));
		exit(1);
		break;

	default: /* parent */
		break;

	}

	/* Give the daemon a chance to start up, and monitor the pipe FD for messages */
	i = 0;
	close(p[1]);

	/* Wait for the process to start or die */
	sleep(1);
	do {
		fd_set fds;
		struct timeval tv={1, 0};
		char message[1024];
		char *messageptr = message;

		FD_ZERO(&fds);
		FD_SET(p[0], &fds);

		status = select(p[0]+1, &fds, NULL, NULL, &tv);

		/* Did we get a cman-reported error? */
		if (status == 1) {
			int len;
			if ((len = read(p[0], message, sizeof(message)) > 0)) {

				/* Forked OK - get the real corosync pid */
				if (sscanf(messageptr, "FORKED: %d", &corosync_pid) == 1) {
					if (comline->verbose & DEBUG_STARTUP_ONLY)
						fprintf(stderr, "forked process ID is %d\n", corosync_pid);
					status = 0;

					/* There might be a SUCCESS or error message in the pipe too. */
					messageptr = strchr(messageptr, '\n');
					if (messageptr && strlen(messageptr) > 1)
						messageptr++;
					else
						continue;
				}
				/* Success! get the new PID of double-forked corosync */
				if (sscanf(messageptr, "SUCCESS: %d", &corosync_pid) == 1) {
					if (comline->verbose & DEBUG_STARTUP_ONLY)
						fprintf(stderr, "corosync running, process ID is %d\n", corosync_pid);
					status = 0;
					break;
				}
				else if (messageptr) {
						fprintf(stderr, "%s\n", messageptr);
						status = 1;
						break;
					}
			}
			else if (len < 0 && errno == EINTR) {
				continue;
			}
			else { /* Error or EOF - check the child status */
				status = check_corosync_status(corosync_pid);
				if (status == 0)
					break;
			}
		}

	} while (status == 0);
	close(p[0]);

	/* If corosync has started, try to connect to cman ... if it's still there */
	if (status == 0) {
		do {
			if (status == 0) {
				if (kill(corosync_pid, 0) < 0) {
					status = check_corosync_status(corosync_pid);
					die("corosync died during startup\n");
				}

				h = cman_admin_init(NULL);
				if (!h && comline->verbose & DEBUG_STARTUP_ONLY)
				{
					fprintf(stderr, "waiting for cman to start\n");
					status = check_corosync_status(corosync_pid);
				}
			}
			sleep (1);
		} while (!h && ++i < 100);
	}

	if (!h)
		die("corosync daemon didn't start");

	if ((comline->verbose & DEBUG_STARTUP_ONLY) && !cman_is_active(h))
		fprintf(stderr, "corosync started, but not joined the cluster yet.\n");

	cman_finish(h);

	/* Copy all COROSYNC_* environment variables into objdb so they can be used to validate new configurations later */
	res = confdb_initialize (&confdb_handle, &callbacks);
	if (res != CS_OK)
		goto join_exit;

	res = confdb_object_create(confdb_handle, OBJECT_PARENT_HANDLE, "cman_private", strlen("cman_private"), &object_handle);
	if (res == CS_OK) {
		int envnum = 0;
		const char *envvar = main_envp[envnum];
		const char *equal;
		char envname[PATH_MAX];


		while (envvar) {
			if (strncmp("COROSYNC_", envvar, 9) == 0) {
				equal = strchr(envvar, '=');
				if (equal) {
				        strncpy(envname, envvar, PATH_MAX);
					if (equal-envvar < PATH_MAX) {
					    envname[equal-envvar] = '\0';

					    res = confdb_key_create_typed(confdb_handle, object_handle, envname,
									  equal+1, strlen(equal+1),CONFDB_VALUETYPE_STRING);
					}
				}
			}
			envvar = main_envp[++envnum];
		}
	}
	res = confdb_key_create_typed(confdb_handle, object_handle,
				      "COROSYNC_DEFAULT_CONFIG_IFACE",
				      config_modules, strlen(config_modules), CONFDB_VALUETYPE_STRING);
	confdb_finalize (confdb_handle);

join_exit:
	return 0;
}
Ejemplo n.º 2
0
int main(int argc, char** argv)
{
	int c;
	char *ubus_socket = UBUS_UNIX_SOCKET;

#ifdef LOG_LEVEL_DEFAULT
	LOG_INIT(APP_NAME, LOG_LEVEL_DEFAULT, STDOUT);
#else
	LOG_INIT(APP_NAME, LR_LOG_INFO, STDOUT);
#endif

	while((c = getopt(argc, argv, "dl:")) != -1)
	{
		switch (c)
		{
			case 'd':
				become_daemon = 0;
				break;
			case 'l':
				{
					char *end;
					long l;
					l = strtoul(optarg, &end, 0);
					if(*optarg == 0 || *end != 0 || l > 10)
					{
						ERROR(DEFAULT_GROUP,"Invalid loglevel %s", optarg);
						exit(1);
					}
					SET_LOG_LEVEL(l);
					break;
				}
			default:
				return -1;
		}
	}

	if(become_daemon){
		LOG_MODE(SYSLOG);
		openlog(APP_NAME, LOG_CONS | LOG_PID, LOG_LOCAL1);
		be_daemon();
	}

	lpd_setup_signals();

	pthread_create(&lpd_thread_id, NULL, (void *)loop_detect_run, NULL);

	if (loop_detect_ubus_init(ubus_socket) < 0) {
		ERROR(DEFAULT_GROUP, "failed to connect to ubus\n");
		return -1;
	}

	
	loop_detect_ubus_run();

	pthread_cancel(lpd_thread_id);
	pthread_join(lpd_thread_id, NULL);

	return 0;


}
Ejemplo n.º 3
0
int main(int argc, char *argv[])
{
	int c;
	char *ubus_socket = UBUS_UNIX_SOCKET;
#if 0
	/* Sanity check */
	{
		bridge_identifier_t BridgeIdentifier;
		mst_configuration_identifier_t MST_ConfigurationIdentifier;
		TST(sizeof(BridgeIdentifier) == 8, -1);
		TST(sizeof(BridgeIdentifier.u) == 8, -1);
		TST(sizeof(BridgeIdentifier.s) == 8, -1);
		TST(sizeof(BridgeIdentifier.s.priority) == 2, -1);
		TST(sizeof(BridgeIdentifier.s.mac_address) == 6, -1);
		TST(sizeof(MST_ConfigurationIdentifier) == 51, -1);
		TST(sizeof(MST_ConfigurationIdentifier.a) == 51, -1);
		TST(sizeof(MST_ConfigurationIdentifier.s) == 51, -1);
#ifdef HMAC_MDS_TEST_FUNCTIONS
		TST(MD5TestSuite(), -1);
#endif /* HMAC_MDS_TEST_FUNCTIONS */
		INFO(GLOBAL_OUT_GROUP,"Sanity checks succeeded");
	}
#endif
#ifdef LOG_LEVEL_DEFAULT
	LOG_INIT("mstpd", LOG_LEVEL_DEFAULT, STDOUT);
#else
	LOG_INIT("mstpd", LR_LOG_INFO, STDOUT);
#endif

	while((c = getopt(argc, argv, "dl:")) != -1)
	{
		switch (c)
		{
			case 'd':
				become_daemon = 0;
				break;
			case 'l':
				{
					char *end;
					long l;
					l = strtoul(optarg, &end, 0);
					if(*optarg == 0 || *end != 0 || l > 10)
					{
						ERROR(GLOBAL_OUT_GROUP,"Invalid loglevel %s", optarg);
						exit(1);
					}
					SET_LOG_LEVEL(l);
					break;
				}
			default:
				return -1;
		}
	}

	if(become_daemon){
		LOG_MODE(SYSLOG);
		openlog(SERVICE_NAME, LOG_CONS | LOG_PID, LOG_LOCAL1);
		be_daemon();
	}

	mstpd_setup_signals();

	int ret,stacksize = 204800;
	pthread_attr_t attr;
	ret = pthread_attr_init(&attr); /*初始化线程属性*/

	if (ret != 0){
		return -1;
	}

	ret = pthread_attr_setstacksize(&attr, stacksize);

	if(ret != 0){
		pthread_attr_destroy(&attr);
		return -1;
	}

	ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
	if(ret != 0){
		pthread_attr_destroy(&attr);
		return -1;
	}

#if 1
	struct sched_param param;
	param.sched_priority  = 90;
	ret = pthread_attr_setschedparam(&attr, &param);
	if(ret != 0){
		pthread_attr_destroy(&attr);
		return -1;
	}

#endif
	
	
	int err = pthread_create(&mstp_thread_id, &attr, (void *)mstpd_run, NULL);
	if (err != 0){
		ERROR(GLOBAL_OUT_GROUP, "can't create thread: %s\n", strerror(err));
		return -1;
	}

	if (mstpd_ubus_init(ubus_socket) < 0) {
		ERROR(GLOBAL_OUT_GROUP, "failed to connect to ubus\n");
		pthread_cancel(mstp_thread_id);
		pthread_join(mstp_thread_id, NULL);
		pthread_attr_destroy(&attr);
		return -1;
	}

	mstpd_ubus_run();

	pthread_cancel(mstp_thread_id);
	pthread_join(mstp_thread_id, NULL);
	pthread_attr_destroy(&attr);

	return 0;
}