forked from MirrorHub/synapse
5cc7564c5c
Optionally start or stop an individual worker by passing -w with the path to the worker config. Optionally start or stop every worker and the main synapse by passing -a with a path to a directory containing worker configs. The "-w" is intended to be used to bounce individual workers proceses. THe "-a" is intended for when you want to restart all the workers simultaneuously, for example when performing database upgrades.
212 lines
6.1 KiB
Python
Executable file
212 lines
6.1 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
# Copyright 2014-2016 OpenMarket Ltd
|
|
#
|
|
# 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.
|
|
|
|
import argparse
|
|
import collections
|
|
import glob
|
|
import os
|
|
import os.path
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
import yaml
|
|
|
|
SYNAPSE = ["python", "-B", "-m", "synapse.app.homeserver"]
|
|
|
|
GREEN = "\x1b[1;32m"
|
|
RED = "\x1b[1;31m"
|
|
NORMAL = "\x1b[m"
|
|
|
|
|
|
def write(message, colour=NORMAL, stream=sys.stdout):
|
|
if colour == NORMAL:
|
|
stream.write(message + "\n")
|
|
else:
|
|
stream.write(colour + message + NORMAL + "\n")
|
|
|
|
|
|
def start(configfile):
|
|
write("Starting ...")
|
|
args = SYNAPSE
|
|
args.extend(["--daemonize", "-c", configfile])
|
|
|
|
try:
|
|
subprocess.check_call(args)
|
|
write("started synapse.app.homeserver(%r)" % (configfile,), colour=GREEN)
|
|
except subprocess.CalledProcessError as e:
|
|
write(
|
|
"error starting (exit code: %d); see above for logs" % e.returncode,
|
|
colour=RED,
|
|
)
|
|
|
|
|
|
def start_worker(app, configfile, worker_configfile):
|
|
args = [
|
|
"python", "-B",
|
|
"-m", app,
|
|
"-c", configfile,
|
|
"-c", worker_configfile
|
|
]
|
|
|
|
try:
|
|
subprocess.check_call(args)
|
|
write("started %s(%r)" % (app, worker_configfile), colour=GREEN)
|
|
except subprocess.CalledProcessError as e:
|
|
write(
|
|
"error starting %s(%r) (exit code: %d); see above for logs" % (
|
|
app, worker_configfile, e.returncode,
|
|
),
|
|
colour=RED,
|
|
)
|
|
|
|
|
|
def stop(pidfile, app):
|
|
if os.path.exists(pidfile):
|
|
pid = int(open(pidfile).read())
|
|
os.kill(pid, signal.SIGTERM)
|
|
write("stopped %s" % (app,), colour=GREEN)
|
|
|
|
|
|
Worker = collections.namedtuple("Worker", [
|
|
"app", "configfile", "pidfile", "cache_factor"
|
|
])
|
|
|
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument(
|
|
"action",
|
|
choices=["start", "stop", "restart"],
|
|
help="whether to start, stop or restart the synapse",
|
|
)
|
|
parser.add_argument(
|
|
"configfile",
|
|
nargs="?",
|
|
default="homeserver.yaml",
|
|
help="the homeserver config file, defaults to homserver.yaml",
|
|
)
|
|
parser.add_argument(
|
|
"-w", "--worker",
|
|
metavar="WORKERCONFIG",
|
|
help="start or stop a single worker",
|
|
)
|
|
parser.add_argument(
|
|
"-a", "--all-processes",
|
|
metavar="WORKERCONFIGDIR",
|
|
help="start or stop all the workers in the given directory"
|
|
" and the main synapse process",
|
|
)
|
|
|
|
options = parser.parse_args()
|
|
|
|
if options.worker and options.all_processes:
|
|
write(
|
|
'Cannot use "--worker" with "--all-processes"',
|
|
stream=sys.stderr
|
|
)
|
|
sys.exit(1)
|
|
|
|
configfile = options.configfile
|
|
|
|
if not os.path.exists(configfile):
|
|
write(
|
|
"No config file found\n"
|
|
"To generate a config file, run '%s -c %s --generate-config"
|
|
" --server-name=<server name>'\n" % (
|
|
" ".join(SYNAPSE), options.configfile
|
|
),
|
|
stream=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
|
|
with open(configfile) as stream:
|
|
config = yaml.load(stream)
|
|
|
|
pidfile = config["pid_file"]
|
|
cache_factor = config.get("synctl_cache_factor")
|
|
start_stop_synapse = True
|
|
|
|
if cache_factor:
|
|
os.environ["SYNAPSE_CACHE_FACTOR"] = str(cache_factor)
|
|
|
|
worker_configfiles = []
|
|
if options.worker:
|
|
start_stop_synapse = False
|
|
worker_configfile = options.worker
|
|
if not os.path.exists(worker_configfile):
|
|
write(
|
|
"No worker config found at %r" % (worker_configfile,),
|
|
stream=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
worker_configfiles.append(worker_configfile)
|
|
|
|
if options.all_processes:
|
|
worker_configdir = options.all_processes
|
|
if not os.path.isdir(worker_configdir):
|
|
write(
|
|
"No worker config directory found at %r" % (worker_configdir,),
|
|
stream=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
worker_configfiles.extend(sorted(glob.glob(
|
|
os.path.join(worker_configdir, "*.yaml")
|
|
)))
|
|
|
|
workers = []
|
|
for worker_configfile in worker_configfiles:
|
|
with open(worker_configfile) as stream:
|
|
worker_config = yaml.load(stream)
|
|
worker_app = worker_config["worker_app"]
|
|
worker_pidfile = worker_config["worker_pid_file"]
|
|
worker_daemonize = worker_config["worker_daemonize"]
|
|
assert worker_daemonize # TODO print something more user friendly
|
|
worker_cache_factor = worker_config.get("synctl_cache_factor")
|
|
workers.append(Worker(
|
|
worker_app, worker_configfile, worker_pidfile, worker_cache_factor,
|
|
))
|
|
|
|
action = options.action
|
|
|
|
if action == "stop" or action == "restart":
|
|
for worker in workers:
|
|
stop(worker.pidfile, worker.app)
|
|
|
|
if start_stop_synapse:
|
|
stop(pidfile, "synapse.app.homeserver")
|
|
|
|
# TODO: Wait for synapse to actually shutdown before starting it again
|
|
|
|
if action == "start" or action == "restart":
|
|
if start_stop_synapse:
|
|
start(configfile)
|
|
|
|
for worker in workers:
|
|
if worker.cache_factor:
|
|
os.environ["SYNAPSE_CACHE_FACTOR"] = str(worker.cache_factor)
|
|
|
|
start_worker(worker.app, configfile, worker.configfile)
|
|
|
|
if cache_factor:
|
|
os.environ["SYNAPSE_CACHE_FACTOR"] = str(cache_factor)
|
|
else:
|
|
os.environ.pop("SYNAPSE_CACHE_FACTOR", None)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|