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; }
static void delay_members(void) { int rv, tries = 0; int cd; cd = ccs_connect(); if (cd < 0) { cman_finish(ch); die("lost cman/ccs connection"); } read_ccs_nodeids(cd); while (1) { rv = all_nodeids_are_members(); if (rv < 0) { ccs_disconnect(cd); cman_finish(ch); die("lost cman connection"); } if (rv) break; tries++; if (opt_delay_members < 0) goto retry_members; if (!opt_delay_members || tries > opt_delay_members) { fprintf(stderr, "%s: continuing without all members\n", prog_name); break; } retry_members: if (!(tries % 10)) fprintf(stderr, "%s: delaying for members\n", prog_name); sleep(1); } ccs_disconnect(cd); return; }
int member_list_nodes(clv_clnode_head_t *cn_head) { int node_count, i; cman_handle_t cman_handle; cman_node_t *cman_nodes, local_node; if ((cman_handle = cman_init(0)) == 0) { return -1; } if ((node_count = cman_get_node_count(cman_handle)) < 0) { return -1; } cman_nodes = calloc((size_t) node_count, sizeof(cman_node_t)); cman_get_nodes(cman_handle, node_count, &node_count, cman_nodes); local_node.cn_name[0] = '\0'; /* init cn_name for cman_get_node */ if (cman_get_node(cman_handle, CMAN_NODEID_US, &local_node) != 0) { return -1; } for (i = 0; i < node_count; i++) { clv_clnode_t *n; n = malloc(sizeof(clv_clnode_t)); STAILQ_INSERT_TAIL(cn_head, n, next); n->id = (uint32_t) cman_nodes[i].cn_nodeid; n->host = strdup(cman_nodes[i].cn_name); n->status = 0; if (cman_nodes[i].cn_member != 0) { n->status |= CLUSTER_NODE_ONLINE; } if (cman_nodes[i].cn_nodeid == local_node.cn_nodeid) { n->status |= CLUSTER_NODE_LOCAL; } } free(cman_nodes); cman_finish(cman_handle); return 0; }
static int connect_cman(void) { int rv, tries = 0; while (1) { ch = cman_init(NULL); if (ch) break; tries++; if (opt_retry_cman < 0) goto retry_init; if (!opt_retry_cman || tries >= opt_retry_cman) return -1; retry_init: if (!(tries % 10)) fprintf(stderr, "%s: retrying cman connection\n", prog_name); sleep(1); } while (1) { rv = cman_is_active(ch); if (rv) break; tries++; if (opt_retry_cman < 0) goto retry_active; if (!opt_retry_cman || tries >= opt_retry_cman) { cman_finish(ch); return -1; } retry_active: if (!(tries % 10)) fprintf(stderr, "%s: retrying cman active check\n", prog_name); sleep(1); } return 0; }
static void do_join(int argc, char *argv[]) { int rv, tries = 0; rv = connect_cman(); if (rv < 0) die("can't connect to cman"); /* if delay_quorum() or delay_members() fail on any cman/ccs connection or operation, they call cman_finish() and exit with failure */ if (opt_delay_quorum) delay_quorum(); if (opt_delay_members) delay_members(); cman_finish(ch); /* This loop deals with the case where fenced is slow enough starting up that fenced_join fails. Do we also want to add a delay here to deal with the case where fenced is so slow starting up that it hasn't locked its lockfile yet, causing check_fenced_running to fail? */ while (1) { rv = fenced_join(); if (!rv) break; check_fenced_running(); tries++; if (!(tries % 10)) fprintf(stderr, "%s: retrying join\n", prog_name); sleep(1); } if (opt_wait_joinleave) wait_domain(1); exit(EXIT_SUCCESS); }
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; }
Quorum::~Quorum() { if (dispatchHandle.get()) dispatchHandle->stopWatch(); dispatchHandle.reset(); if (cman) cman_finish(cman); }
Quorum::~Quorum() { dispatchHandle.reset(); if (cman) cman_finish(cman); }