Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 260 lines (216 sloc) 8.67 kb
5cf2edd @seanlynch Replace gen_cluster_scripts.rb with cluster_run.
seanlynch authored
1 #!/usr/bin/env python
c0612ad @alk [cluster_run] always rename cluster nodes by default
alk authored
2 import os, subprocess, sys, signal, termios, atexit, socket, getopt
5cf2edd @seanlynch Replace gen_cluster_scripts.rb with cluster_run.
seanlynch authored
3
d2f1015 @alk make sure erlang VMs get SIGHUP when cluster_run script dies
alk authored
4 def testament_child_death():
5 rv = os.fork()
6 if rv == 0:
7 os.kill(os.getpid(), signal.SIGSTOP)
8 os._exit(0)
9 os.waitpid(rv, os.WUNTRACED)
10
0963a0f @alk implemented make install with new directory layout
alk authored
11 PREFIX = subprocess.Popen(". $(pwd)/.configuration && echo $prefix", shell = True, stdout=subprocess.PIPE).communicate()[0].rstrip()
26cb6e5 @alk use couchdb symlink in lib
alk authored
12
3212a5d @alk enabled dev-mode clusters backed by couch
alk authored
13 base_direct_port = 12000
14 base_api_port = 9000
15 base_couch_port = 9500
16 base_mccouch_port = 13000
17
bb87f66 @aartamonau Add --loglevel option to cluster_run.
aartamonau authored
18 LOGGERS = ["default", "couchdb", "ns_server",
19 "error_logger", "user", "menelaus",
20 "ns_doctor", "stats", "rebalance", "cluster"]
21
22 LOGLEVELS = ["debug", "info", "warn", "error", "critical"]
3212a5d @alk enabled dev-mode clusters backed by couch
alk authored
23
b92ce05 @alk don't fail if couch is not present
alk authored
24 def setup_path():
25 def ebin_search(path):
26 return subprocess.Popen(["find", path, "-name", "ebin", "-type", "d"],
27 stdout=subprocess.PIPE).communicate()[0].split()
28
29 path = ebin_search(".")
0963a0f @alk implemented make install with new directory layout
alk authored
30 couchpath = ebin_search("{0}/lib/couchdb/erlang/lib".format(PREFIX))
3212a5d @alk enabled dev-mode clusters backed by couch
alk authored
31 couch_plugins = ebin_search("{0}/lib/couchdb/plugins".format(PREFIX))
b92ce05 @alk don't fail if couch is not present
alk authored
32
33 if len(couchpath) == 0:
58b321f option to stop ns_server from starting
Dale Harvey authored
34 print("Couch libs wasn't found. Will disable couch support\n")
35 os.environ['DONT_START_COUCH'] = '1'
b92ce05 @alk don't fail if couch is not present
alk authored
36
3212a5d @alk enabled dev-mode clusters backed by couch
alk authored
37 return couchpath + path + couch_plugins
38
39 def mk_node_couch_config(i):
40 try:
41 os.mkdir("couch")
42 except os.error:
43 pass
44
45 with open("couch/n_{0}_conf.ini".format(i), "w") as f:
46 f.write("[httpd]\n")
47 f.write("port={0}\n".format(base_couch_port + i))
48 f.write("[couchdb]\n")
49 f.write("database_dir={0}/couch/{1}\n".format(os.getcwd(), i))
50 f.write("view_index_dir={0}/couch/{1}\n".format(os.getcwd(), i))
51 f.write("max_dbs_open=10000\n")
52 f.write("[log]\n")
53 f.write("file={0}/couch/{1}.log\n".format(os.getcwd(), i))
54 f.write("[daemons]\n")
55 f.write("mc_daemon={{mc_sup, start_link, [{0}]}}\n".format(base_mccouch_port+i))
b92ce05 @alk don't fail if couch is not present
alk authored
56
3212a5d @alk enabled dev-mode clusters backed by couch
alk authored
57 def couch_configs(i):
58 mk_node_couch_config(i)
59 return ["{0}/etc/couchdb/default.ini".format(PREFIX),
3a8884b @alk added initial CAPI db-frontend implementation
alk authored
60 "{0}/etc/couchdb/default.d/capi.ini".format(PREFIX),
cb19615 @vmx Update for GeoCouch config location change.
vmx authored
61 "{0}/etc/couchdb/default.d/geocouch.ini".format(PREFIX),
3212a5d @alk enabled dev-mode clusters backed by couch
alk authored
62 "couch/n_{0}_conf.ini".format(i)]
b92ce05 @alk don't fail if couch is not present
alk authored
63
a67fbf7 @dustin Allow OS-specific hacks with cluster_run
dustin authored
64 def os_specific(args, params):
65 """Add os-specific junk to the cluster startup."""
66 import platform
67
68 if platform.system() == 'Darwin':
69 import resource
70 ## OS X has a pretty tiny default fd limit. Let's increase it
71 resource.setrlimit(resource.RLIMIT_NOFILE, (2048, 2048))
72 ## Also, we build stuff in kind of dumb ways, so fix the path.
73 dypath = ("%(pwd)s/../install/lib/memcached:"
74 "%(pwd)s/../install/lib:/usr/local/lib") % {'pwd': os.getcwd()}
ab40dd2 @aartamonau Set ERL_MAX_PORTS on Mac OS X in cluster_run.
aartamonau authored
75 params['env'] = {"DYLD_LIBRARY_PATH": dypath,
76 "ERL_MAX_PORTS": "2048"}
a67fbf7 @dustin Allow OS-specific hacks with cluster_run
dustin authored
77 params['env'].update(os.environ)
78
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
79 def start_cluster(num_nodes, start_index, host, extra_args):
b92ce05 @alk don't fail if couch is not present
alk authored
80 ebin_path = setup_path()
81
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
82 def start_node(i):
83 logdir = "logs/n_{0}".format(i)
5cf2edd @seanlynch Replace gen_cluster_scripts.rb with cluster_run.
seanlynch authored
84 try:
85 os.makedirs(logdir)
86 except:
87 pass
0963a0f @alk implemented make install with new directory layout
alk authored
88 try:
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
89 os.stat("data/n_{0}/mnesia".format(i))
0963a0f @alk implemented make install with new directory layout
alk authored
90 except:
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
91 os.makedirs("data/n_{0}/mnesia".format(i))
ccf8902 @Damienkatz Disable processor thread binding in ns_server/cluster_run.
Damienkatz authored
92 args = ["erl", "+A", "16", "+sbtu", "-pa"] + ebin_path + [
de9fb03 @seanlynch Support forced renaming with cluster_run
seanlynch authored
93 "-setcookie", "nocookie",
94 "-kernel", "inet_dist_listen_min", "21100",
95 "inet_dist_listen_max", "21199",
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
96 "-couch_ini"] + couch_configs(i) + [
0963a0f @alk implemented make install with new directory layout
alk authored
97 "-ns_server", "config_path", '"etc/static_config.in"',
98 "error_logger_mf_dir", '"{0}"'.format(logdir),
de9fb03 @seanlynch Support forced renaming with cluster_run
seanlynch authored
99 "error_logger_mf_maxbytes", "10485760",
100 "error_logger_mf_maxfiles", "10",
ac839ad @alk don't disable stderr logging for cluster_run
alk authored
101 "dont_suppress_stderr_logger", "true",
0963a0f @alk implemented make install with new directory layout
alk authored
102 "path_config_etcdir", '"priv"',
103 "path_config_bindir", '"{0}"'.format(PREFIX+"/bin"),
104 "path_config_libdir", '"{0}"'.format(PREFIX+"/lib"),
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
105 "path_config_datadir", '"data/n_{0}"'.format(i),
0963a0f @alk implemented make install with new directory layout
alk authored
106 "path_config_tmpdir", '"tmp/"',
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
107 "rest_port", str(base_api_port + i),
108 "mccouch_port", str(base_mccouch_port + i),
e220d5a @aartamonau MB-4023 Use memcached port dedicated specifically to ns_server.
aartamonau authored
109 "memcached_port", str(base_direct_port + i * 3),
110 "memcached_dedicated_port", str(base_direct_port + i * 3 + 1),
111 "moxi_port", str(base_direct_port + i * 3 + 2),
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
112 "short_name", '"n_{0}"'.format(i)
113 ] + extra_args
a67fbf7 @dustin Allow OS-specific hacks with cluster_run
dustin authored
114
115 params = {}
116
117 if i > 0:
118 args += ['-noshell']
119 params['stdin'] = subprocess.PIPE
120
121 os_specific(args, params)
122
2faf852 @Damienkatz Add more aggressive erlang GC
Damienkatz authored
123 if not params.has_key('env'):
124 params['env'] = {}
125 params['env'].update(os.environ)
126 params['env'].update({'ERL_FULLSWEEP_AFTER':'0'})
a67fbf7 @dustin Allow OS-specific hacks with cluster_run
dustin authored
127 return subprocess.Popen(args, **params)
5cf2edd @seanlynch Replace gen_cluster_scripts.rb with cluster_run.
seanlynch authored
128
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
129 return [start_node(i + start_index) for i in xrange(num_nodes)]
5cf2edd @seanlynch Replace gen_cluster_scripts.rb with cluster_run.
seanlynch authored
130
131 def usage():
5e7199d @aartamonau Update cluster_run usage information.
aartamonau authored
132 sys.exit("Usage: {0} [--nodes=N] [--dont-rename] [--dont-start] "
133 "[--interactive] [--static-cookie] [--start-index=N] "
bb87f66 @aartamonau Add --loglevel option to cluster_run.
aartamonau authored
134 "[--static-cookie] [--host=H] [--loglevel=L] "
5e7199d @aartamonau Update cluster_run usage information.
aartamonau authored
135 "[ns_server args]".format(sys.argv[0]))
5cf2edd @seanlynch Replace gen_cluster_scripts.rb with cluster_run.
seanlynch authored
136
95d03cf @alk [cluster_run] spawn epmd if it's not running
alk authored
137 def maybe_spawn_epmd():
138 try:
139 socket.create_connection(("127.0.0.1", 4369)).close()
140 except socket.error:
141 print("Spawning epmd...\n")
142 subprocess.Popen("erl -noshell -setcookie nocookie -sname init -run init stop 2>&1 > /dev/null",
143 shell = True).communicate()
144
c0612ad @alk [cluster_run] always rename cluster nodes by default
alk authored
145 def find_primary_addr():
146 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
147 try:
148 s.connect(("8.8.8.8", 56))
149 addr, port = s.getsockname()
150 return addr
151 except socket.error:
152 return None
153 finally:
154 s.close()
5cf2edd @seanlynch Replace gen_cluster_scripts.rb with cluster_run.
seanlynch authored
155
156 def main():
157 try:
bb87f66 @aartamonau Add --loglevel option to cluster_run.
aartamonau authored
158 optlist, args = getopt.gnu_getopt(sys.argv[1:], "hn:i",
159 ["help", "start-index=", "nodes=",
160 "dont-rename", "interactive",
161 "static-cookie", "dont-start",
162 "host=", "loglevel="])
c0612ad @alk [cluster_run] always rename cluster nodes by default
alk authored
163 except getopt.GetoptError, err:
164 # print help information and exit:
165 print str(err) # will print something like "option -a not recognized"
166 usage()
167 sys.exit(2)
168
4ede441 @alk Do rename dev-mode nodes.
alk authored
169 dont_rename = False
58b321f option to stop ns_server from starting
Dale Harvey authored
170 dont_start = False
9996ab9 add an option to not rename cookies
Dale Harvey authored
171 static_cookie = False
6aec6fc Disable interactive shell by default, enable with -i
Dale Harvey authored
172 interactive_shell = False
e6a9f27 allow independent cluster_runs in parallel
Dale Harvey authored
173 start_index = 0
174 num_nodes = 1
4ede441 @alk Do rename dev-mode nodes.
alk authored
175 host = "127.0.0.1"
bb87f66 @aartamonau Add --loglevel option to cluster_run.
aartamonau authored
176 loglevel = None
c0612ad @alk [cluster_run] always rename cluster nodes by default
alk authored
177
178 for o, a in optlist:
e6a9f27 allow independent cluster_runs in parallel
Dale Harvey authored
179 if o in ("--nodes", "-n"):
180 num_nodes = int(a)
6aec6fc Disable interactive shell by default, enable with -i
Dale Harvey authored
181 elif o in ("--interactive", "-i"):
182 interactive_shell = True
e6a9f27 allow independent cluster_runs in parallel
Dale Harvey authored
183 elif o == '--dont-start':
58b321f option to stop ns_server from starting
Dale Harvey authored
184 dont_start = True
e6a9f27 allow independent cluster_runs in parallel
Dale Harvey authored
185 elif o == '--host':
186 host = a
187 elif o == '--start-index':
188 start_index = int(a)
4ede441 @alk Do rename dev-mode nodes.
alk authored
189 elif o == '--dont-rename':
190 dont_rename = True
c0612ad @alk [cluster_run] always rename cluster nodes by default
alk authored
191 elif o in ("--help", "-h"):
192 usage()
193 exit(0)
9996ab9 add an option to not rename cookies
Dale Harvey authored
194 elif o in("--static-cookie"):
195 static_cookie = True
bb87f66 @aartamonau Add --loglevel option to cluster_run.
aartamonau authored
196 elif o == '--loglevel':
197 loglevel = a
c0612ad @alk [cluster_run] always rename cluster nodes by default
alk authored
198 else:
199 assert False, "unhandled options"
200
2f7837d @alk [cluster_run] always kill erlangs and start shell on first
alk authored
201 nodes = []
dbb3506 @alk [cluster_run] restore terminal attrs in atexit handler
alk authored
202 terminal_attrs = None
2f7837d @alk [cluster_run] always kill erlangs and start shell on first
alk authored
203
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
204 def kill_nodes(*args):
2f7837d @alk [cluster_run] always kill erlangs and start shell on first
alk authored
205 for n in nodes:
206 try:
207 n.kill()
ede590c @alk [cluster_run] wait childs death
alk authored
208 n.wait()
2f7837d @alk [cluster_run] always kill erlangs and start shell on first
alk authored
209 except OSError:
210 pass
dbb3506 @alk [cluster_run] restore terminal attrs in atexit handler
alk authored
211 if terminal_attrs != None:
212 termios.tcsetattr(sys.stdin, termios.TCSANOW, terminal_attrs)
2f7837d @alk [cluster_run] always kill erlangs and start shell on first
alk authored
213
eacc3de @alk Revert "Shutdown ns_server gracefully from within cluster_run."
alk authored
214 atexit.register(kill_nodes)
2f7837d @alk [cluster_run] always kill erlangs and start shell on first
alk authored
215
d2f1015 @alk make sure erlang VMs get SIGHUP when cluster_run script dies
alk authored
216 testament_child_death()
217
8b2ea0a @alk [cluster_run] don't screw up when stdin is not terminal
alk authored
218 try:
219 terminal_attrs = termios.tcgetattr(sys.stdin)
220 except:
221 pass
2f7837d @alk [cluster_run] always kill erlangs and start shell on first
alk authored
222
95d03cf @alk [cluster_run] spawn epmd if it's not running
alk authored
223 maybe_spawn_epmd()
224
4ede441 @alk Do rename dev-mode nodes.
alk authored
225 extra_args = []
226 if not dont_rename:
227 primary_addr = find_primary_addr()
228 if primary_addr == None:
229 print("was unable to detect 'internet' address of this machine."
230 + " node rename will be disabled")
231 else:
232 extra_args += ["rename_ip", '"' + primary_addr + '"']
233 extra_args += args[1:]
c0612ad @alk [cluster_run] always rename cluster nodes by default
alk authored
234
9996ab9 add an option to not rename cookies
Dale Harvey authored
235 if static_cookie:
236 extra_args += ["-ns_server", "dont_reset_cookie", "true"]
237
58b321f option to stop ns_server from starting
Dale Harvey authored
238 if not dont_start:
239 extra_args += ["-run", "ns_bootstrap"]
240
6aec6fc Disable interactive shell by default, enable with -i
Dale Harvey authored
241 if not interactive_shell:
242 extra_args += ["-noinput"]
243
bb87f66 @aartamonau Add --loglevel option to cluster_run.
aartamonau authored
244 if loglevel is not None:
245 if loglevel not in LOGLEVELS:
246 print "Valid log levels are the following: %s" % ', '.join(LOGLEVELS)
247 sys.exit(1)
248
249 for logger in LOGGERS:
250 extra_args += ["-ns_server", "loglevel_%s" % logger, loglevel]
251
e6a9f27 allow independent cluster_runs in parallel
Dale Harvey authored
252 nodes = start_cluster(num_nodes, start_index, host, extra_args)
2f7837d @alk [cluster_run] always kill erlangs and start shell on first
alk authored
253
5cf2edd @seanlynch Replace gen_cluster_scripts.rb with cluster_run.
seanlynch authored
254 for node in nodes:
255 node.wait()
256
257
258 if __name__ == '__main__':
259 main()
Something went wrong with that request. Please try again.