Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 259 lines (215 sloc) 8.595 kB
#!/usr/bin/env python
import os, subprocess, sys, signal, termios, atexit, socket, getopt
def testament_child_death():
rv = os.fork()
if rv == 0:
os.kill(os.getpid(), signal.SIGSTOP)
os._exit(0)
os.waitpid(rv, os.WUNTRACED)
PREFIX = subprocess.Popen(". $(pwd)/.configuration && echo $prefix", shell = True, stdout=subprocess.PIPE).communicate()[0].rstrip()
base_direct_port = 12000
base_api_port = 9000
base_couch_port = 9500
base_mccouch_port = 13000
LOGGERS = ["default", "couchdb", "ns_server",
"error_logger", "user", "menelaus",
"ns_doctor", "stats", "rebalance", "cluster"]
LOGLEVELS = ["debug", "info", "warn", "error", "critical"]
def setup_path():
def ebin_search(path):
return subprocess.Popen(["find", path, "-name", "ebin", "-type", "d"],
stdout=subprocess.PIPE).communicate()[0].split()
path = ebin_search(".")
couchpath = ebin_search("{0}/lib/couchdb/erlang/lib".format(PREFIX))
couch_plugins = ebin_search("{0}/lib/couchdb/plugins".format(PREFIX))
if len(couchpath) == 0:
print("Couch libs wasn't found. Will disable couch support\n")
os.environ['DONT_START_COUCH'] = '1'
return couchpath + path + couch_plugins
def mk_node_couch_config(i):
try:
os.mkdir("couch")
except os.error:
pass
with open("couch/n_{0}_conf.ini".format(i), "w") as f:
f.write("[httpd]\n")
f.write("port={0}\n".format(base_couch_port + i))
f.write("[couchdb]\n")
f.write("database_dir={0}/couch/{1}\n".format(os.getcwd(), i))
f.write("view_index_dir={0}/couch/{1}\n".format(os.getcwd(), i))
f.write("max_dbs_open=10000\n")
f.write("[log]\n")
f.write("file={0}/couch/{1}.log\n".format(os.getcwd(), i))
f.write("[daemons]\n")
f.write("mc_daemon={{mc_sup, start_link, [{0}]}}\n".format(base_mccouch_port+i))
def couch_configs(i):
mk_node_couch_config(i)
return ["{0}/etc/couchdb/default.ini".format(PREFIX),
"{0}/etc/couchdb/default.d/capi.ini".format(PREFIX),
"{0}/etc/couchdb/default.d/geocouch.ini".format(PREFIX),
"couch/n_{0}_conf.ini".format(i)]
def os_specific(args, params):
"""Add os-specific junk to the cluster startup."""
import platform
if platform.system() == 'Darwin':
import resource
## OS X has a pretty tiny default fd limit. Let's increase it
resource.setrlimit(resource.RLIMIT_NOFILE, (2048, 2048))
## Also, we build stuff in kind of dumb ways, so fix the path.
dypath = ("%(pwd)s/../install/lib/memcached:"
"%(pwd)s/../install/lib:/usr/local/lib") % {'pwd': os.getcwd()}
params['env'] = {"DYLD_LIBRARY_PATH": dypath,
"ERL_MAX_PORTS": "2048"}
params['env'].update(os.environ)
def start_cluster(num_nodes, start_index, host, extra_args):
ebin_path = setup_path()
def start_node(i):
logdir = "logs/n_{0}".format(i)
try:
os.makedirs(logdir)
except:
pass
try:
os.stat("data/n_{0}/mnesia".format(i))
except:
os.makedirs("data/n_{0}/mnesia".format(i))
args = ["erl", "+A", "16", "+sbtu", "-pa"] + ebin_path + [
"-setcookie", "nocookie",
"-kernel", "inet_dist_listen_min", "21100",
"inet_dist_listen_max", "21199",
"-couch_ini"] + couch_configs(i) + [
"-ns_server", "config_path", '"etc/static_config.in"',
"error_logger_mf_dir", '"{0}"'.format(logdir),
"error_logger_mf_maxbytes", "10485760",
"error_logger_mf_maxfiles", "10",
"dont_suppress_stderr_logger", "true",
"path_config_etcdir", '"priv"',
"path_config_bindir", '"{0}"'.format(PREFIX+"/bin"),
"path_config_libdir", '"{0}"'.format(PREFIX+"/lib"),
"path_config_datadir", '"data/n_{0}"'.format(i),
"path_config_tmpdir", '"tmp/"',
"rest_port", str(base_api_port + i),
"memcached_port", str(base_direct_port + i * 2),
"mccouch_port", str(base_mccouch_port + i),
"moxi_port", str(base_direct_port + i * 2 + 1),
"short_name", '"n_{0}"'.format(i)
] + extra_args
params = {}
if i > 0:
args += ['-noshell']
params['stdin'] = subprocess.PIPE
os_specific(args, params)
if not params.has_key('env'):
params['env'] = {}
params['env'].update(os.environ)
params['env'].update({'ERL_FULLSWEEP_AFTER':'0'})
return subprocess.Popen(args, **params)
return [start_node(i + start_index) for i in xrange(num_nodes)]
def usage():
sys.exit("Usage: {0} [--nodes=N] [--dont-rename] [--dont-start] "
"[--interactive] [--static-cookie] [--start-index=N] "
"[--static-cookie] [--host=H] [--loglevel=L] "
"[ns_server args]".format(sys.argv[0]))
def maybe_spawn_epmd():
try:
socket.create_connection(("127.0.0.1", 4369)).close()
except socket.error:
print("Spawning epmd...\n")
subprocess.Popen("erl -noshell -setcookie nocookie -sname init -run init stop 2>&1 > /dev/null",
shell = True).communicate()
def find_primary_addr():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(("8.8.8.8", 56))
addr, port = s.getsockname()
return addr
except socket.error:
return None
finally:
s.close()
def main():
try:
optlist, args = getopt.gnu_getopt(sys.argv[1:], "hn:i",
["help", "start-index=", "nodes=",
"dont-rename", "interactive",
"static-cookie", "dont-start",
"host=", "loglevel="])
except getopt.GetoptError, err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
dont_rename = False
dont_start = False
static_cookie = False
interactive_shell = False
start_index = 0
num_nodes = 1
host = "127.0.0.1"
loglevel = None
for o, a in optlist:
if o in ("--nodes", "-n"):
num_nodes = int(a)
elif o in ("--interactive", "-i"):
interactive_shell = True
elif o == '--dont-start':
dont_start = True
elif o == '--host':
host = a
elif o == '--start-index':
start_index = int(a)
elif o == '--dont-rename':
dont_rename = True
elif o in ("--help", "-h"):
usage()
exit(0)
elif o in("--static-cookie"):
static_cookie = True
elif o == '--loglevel':
loglevel = a
else:
assert False, "unhandled options"
nodes = []
terminal_attrs = None
def kill_nodes(*args):
for n in nodes:
try:
n.kill()
n.wait()
except OSError:
pass
if terminal_attrs != None:
termios.tcsetattr(sys.stdin, termios.TCSANOW, terminal_attrs)
atexit.register(kill_nodes)
testament_child_death()
try:
terminal_attrs = termios.tcgetattr(sys.stdin)
except:
pass
maybe_spawn_epmd()
extra_args = []
if not dont_rename:
primary_addr = find_primary_addr()
if primary_addr == None:
print("was unable to detect 'internet' address of this machine."
+ " node rename will be disabled")
else:
extra_args += ["rename_ip", '"' + primary_addr + '"']
extra_args += args[1:]
if static_cookie:
extra_args += ["-ns_server", "dont_reset_cookie", "true"]
if not dont_start:
extra_args += ["-run", "ns_bootstrap"]
if not interactive_shell:
extra_args += ["-noinput"]
if loglevel is not None:
if loglevel not in LOGLEVELS:
print "Valid log levels are the following: %s" % ', '.join(LOGLEVELS)
sys.exit(1)
for logger in LOGGERS:
extra_args += ["-ns_server", "loglevel_%s" % logger, loglevel]
nodes = start_cluster(num_nodes, start_index, host, extra_args)
for node in nodes:
node.wait()
if __name__ == '__main__':
main()
Jump to Line
Something went wrong with that request. Please try again.