forked from rethinkdb/rethinkdb_rebirth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspin_up_cluster
executable file
·208 lines (173 loc) · 8.02 KB
/
spin_up_cluster
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/usr/bin/env python
# Copyright 2018-present RebirthDB
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use
# this file except in compliance with the License. You may obtain a copy of the
# License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
# This file incorporates work covered by the following copyright:
#
# Copyright 2010-present, The Linux Foundation, portions copyright Google and
# others and used with permission or subject to their respective license
# agreements.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import print_function
import copy, optparse, os, signal, subprocess, sys, time
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir, 'test', 'common')))
import driver, utils
# == signal handler
keepRunning = True
def sigintHandler(signal, frame):
global keepRunning
print('\nShutting down servers')
keepRunning = False
signal.signal(signal.SIGINT, sigintHandler)
# == main
def main():
# -- parse input
parser = optparse.OptionParser()
parser.add_option('-b', '--binary', dest='binary', metavar='EXECUTABLE', default=None)
parser.add_option( '--cache-size', dest='cache_size', metavar='MEGABYTES', default=None, type="int")
parser.add_option( '--cores', dest='cores', metavar='COUNT', default=None, type="int")
parser.add_option( '--direct-io', dest='direct_io', action='store_true', default=False)
parser.add_option( '--io-threads', dest='io_threads', metavar='COUNT', default=None, type="int")
parser.add_option('-o', '--output-dir', dest='output_dir', metavar='DIRNAME', default=None)
parser.add_option('-s', '--servers', dest='servers', metavar='COUNT', default=2, type="int")
parser.add_option( '--tls', dest='tls', action='store_true', default=False)
options, args = parser.parse_args()
options.valgrind = False
# -- validate options
if options.binary is not None:
if os.path.isfile(options.binary) and os.access(options.binary, os.X_OK):
options.binary = os.path.realpath(options.binary)
if 'valgrind' in os.path.basename(os.path.dirname(options.binary)):
options.valgrind = True
else:
parser.error('-b/--binary does not exist or is not runnable')
else:
try:
options.binary = utils.find_rebirthdb_executable()
except Exception as e:
parser.error(str(e))
if options.cores is not None and options.cores < 1:
parser.error('--cores must be greater than 1')
if options.servers is not None and options.servers < 1:
parser.error('--servers must be greater than 1')
# -- setup the options
# - options
extraOptions = []
if options.cache_size:
extraOptions += ['--cache-size', str(options.cache_size)]
if options.cores:
extraOptions += ['--cores', str(options.cores)]
if options.direct_io:
extraOptions += ['--direct-io']
if options.io_threads:
if options.io_threads < 1:
parser.error('--io-threads must be 1 or greater')
extraOptions += ['--io-threads', str(options.io_threads)]
if options.output_dir:
if os.path.exists(options.output_dir) and not os.path.isdir(options.output_dir):
parser.error('A file already existed at the -o/--output-dir location: %s' % options.output_dir)
options.output_dir = os.path.realpath(options.output_dir)
if not os.path.exists(os.path.dirname(options.output_dir)):
parser.error('The parent directory of -o/--output-dir does not exist: %s' % os.path.dirname(options.output_dir))
if not os.path.exists(options.output_dir):
try:
os.mkdir(options.output_dir)
except Exception as e:
parser.error('Unable to create ouput dir: %s' % e)
# - command prefix
commandPrefix = []
if options.valgrind:
print('Valgrind build detected, using it')
commandPrefix = ['valgrind', '--leak-check=full', '--track-origins=yes', '--suppressions=' + os.path.join(__file__, 'rebirthdb-valgrind-suppressions.supp')]
# -- print the server information
print(options.binary)
versionString = ''
try:
versionString, _ = subprocess.Popen([options.binary, '--version'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
except Exception as e:
parser.error('Unable to get RebirthDB version: %s' % str(e))
print('Using rebirthdb binary from: %s\n\tversion: %s' % (options.binary, versionString.strip()))
# -- start the cluster
cluster = None
try:
cluster = driver.Cluster(
initial_servers = options.servers,
output_folder = options.output_dir,
console_output = True,
executable_path = options.binary,
command_prefix = commandPrefix,
extra_options = extraOptions,
tls = options.tls
)
except Exception as e:
parser.error('Starting the cluster failed! %s' % str(e))
# - print the cluster information
print('\t%sdata dir: %s' % ('' if options.output_dir else 'temporary ', cluster.output_folder))
if options.tls:
print('\tcert: %s' % cluster.tlsCertPath)
for server in cluster:
print('''\
Server %(name)s (pid: %(pid)d)
data folder: %(folder)s
cluster port: %(cluster)d
driver port: %(driver)d
web admin: http%(secure)s://%(host)s:%(http)s''' % {
'name':server.name,
'pid':server.pid,
'folder':server.data_path,
'cluster':server.cluster_port,
'driver':server.driver_port,
'host':server.host,
'secure':'s' if options.tls else '',
'http':server.http_port
})
print('To shut down servers use ctl-c')
# -- wait for cluster to close, or cmd-c
monitoredServers = cluster[:] # copy the list
while keepRunning:
if monitoredServers:
time.sleep(0.2)
for server in copy.copy(monitoredServers):
if not server.running:
if server.returncode == 0:
print('Server %s exited cleanly' % server.name)
else:
consoleOutput = server.console_output
print('\nServer %s exited with code: %r%s' % (server.name, server.returncode, '\n<<<<<<<<\n' + consoleOutput + ">>>>>>>>\n" if consoleOutput else ''))
monitoredServers.remove(server)
else:
if options.output_dir:
print('No servers still running')
else:
print('No servers still running, waiting for ctl-c to keep files')
if hasattr(signal, 'pause'):
signal.pause()
else:
while True:
time.sleep(10)
try:
cluster.check_and_stop()
except Exception: pass
if __name__ == '__main__':
main()