seafile-containerized/scripts/bootstrap.py

180 lines
5.4 KiB
Python
Raw Normal View History

#!/usr/bin/env python
#coding: UTF-8
"""
This script calls the appropriate seafile init scripts (e.g.
setup-seafile.sh or setup-seafile-mysql.sh. It's supposed to run inside the
container.
"""
2016-11-16 01:46:08 +00:00
import argparse
import os
from os.path import abspath, basename, exists, dirname, join, isdir
import shutil
import sys
import uuid
import time
2016-11-17 04:40:35 +00:00
from utils import (
2016-11-21 02:50:30 +00:00
call, get_conf, get_install_dir, show_progress,
get_script, render_template, get_seafile_version, eprint,
cert_has_valid_days
2016-11-17 04:40:35 +00:00
)
seafile_version = get_seafile_version()
installdir = get_install_dir()
topdir = dirname(installdir)
shared_seafiledir = '/shared/seafile'
ssl_dir = '/shared/ssl'
generated_dir = '/bootstrap/generated'
def init_letsencrypt():
2016-11-17 04:40:35 +00:00
show_progress('Preparing for letsencrypt ...')
if not exists(ssl_dir):
os.mkdir(ssl_dir)
domain = get_conf('server.hostname')
context = {
'ssl_dir': ssl_dir,
'domain': domain,
}
render_template(
'/templates/letsencrypt.cron.template',
join(generated_dir, 'letsencrypt.cron'),
context
)
ssl_crt = '/shared/ssl/{}.crt'.format(domain)
if exists(ssl_crt):
show_progress('Found existing cert file {}'.format(ssl_crt))
if cert_has_valid_days(ssl_crt, 30):
show_progress('Skip letsencrypt verification since we have a valid certificate')
return
show_progress('Starting letsencrypt verification')
# Create a temporary nginx conf to start a server, which would accessed by letsencrypt
context = {
'https': False,
'domain': domain,
}
render_template('/templates/seafile.nginx.conf.template',
'/etc/nginx/sites-enabled/seafile.nginx.conf', context)
# TODO: The 5 seconds heuristic is not good, how can we know for sure nginx is ready?
2016-11-25 06:26:08 +00:00
print 'waiting for nginx server to be ready'
time.sleep(5)
call('nginx -s reload')
call('/scripts/ssl.sh {0} {1}'.format(ssl_dir, domain))
2016-11-17 04:40:35 +00:00
# if call('/scripts/ssl.sh {0} {1}'.format(ssl_dir, domain), check_call=False) != 0:
# eprint('Now waiting 1000s for postmortem')
# time.sleep(1000)
# sys.exit(1)
2016-11-25 06:14:30 +00:00
def generate_local_nginx_conf():
# Now create the final nginx configuratin
domain = get_conf('server.hostname')
context = {
2016-11-25 06:14:30 +00:00
'https': is_https(),
'domain': domain,
}
render_template(
2016-11-25 06:14:30 +00:00
'/templates/seafile.nginx.conf.template',
join(generated_dir, 'seafile.nginx.conf'),
context
)
2016-11-25 06:14:30 +00:00
def is_https():
return get_conf('server.letsencrypt', '').lower() == 'true'
def generate_local_dockerfile():
2016-11-17 04:40:35 +00:00
show_progress('Generating local Dockerfile ...')
context = {
'seafile_version': seafile_version,
'https': is_https(),
'domain': get_conf('server.domain'),
}
render_template('/templates/Dockerfile.template', join(generated_dir, 'Dockerfile'), context)
2016-11-16 01:46:08 +00:00
def parse_args():
ap = argparse.ArgumentParser()
ap.add_argument('--parse-ports', action='store_true')
return ap.parse_args()
def do_parse_ports():
"""
Parse the server.port_mappings option and print docker command line port
mapping flags like "-p 80:80 -p 443:443"
"""
# conf is like '80:80,443:443'
conf = get_conf('server.port_mappings', '').strip()
if conf:
sys.stdout.write(' '.join(['-p {}'.format(part.strip()) for part in conf.split(',')]))
sys.stdout.flush()
def init_seafile_server():
if exists(join(shared_seafiledir, 'seafile-data')):
2016-11-25 07:50:34 +00:00
show_progress('Skip running setup-seafile-mysql.py because there is existing seafile-data folder.')
return
2016-11-17 04:40:35 +00:00
show_progress('Now running setup-seafile-mysql.py in auto mode.')
env = {
'SERVER_NAME': 'seafile',
'SERVER_IP': get_conf('server.hostname'),
'MYSQL_USER': 'seafile',
'MYSQL_USER_PASSWD': str(uuid.uuid4()),
'MYSQL_USER_HOST': '127.0.0.1',
# Default MariaDB root user has empty password and can only connect from localhost.
'MYSQL_ROOT_PASSWD': '',
}
# Change the script to allow mysql root password to be empty
call('''sed -i -e 's/if not mysql_root_passwd/if not mysql_root_passwd and "MYSQL_ROOT_PASSWD" not in os.environ/g' {}'''
.format(get_script('setup-seafile-mysql.py')))
setup_script = get_script('setup-seafile-mysql.sh')
call('{} auto -n seafile'.format(setup_script), env=env)
domain = get_conf('server.hostname')
proto = 'https' if is_https() else 'http'
with open(join(topdir, 'conf', 'seahub_settings.py'), 'a+') as fp:
fp.write('\n')
fp.write('FILE_SERVER_ROOT = "{proto}://{domain}/seafhttp"'.format(proto=proto, domain=domain))
fp.write('\n')
files_to_copy = ['conf', 'ccnet', 'seafile-data', 'seahub-data',]
for fn in files_to_copy:
src = join(topdir, fn)
dst = join(shared_seafiledir, fn)
if not exists(dst) and exists(src):
shutil.move(src, shared_seafiledir)
2016-11-17 04:40:35 +00:00
def main():
args = parse_args()
if args.parse_ports:
do_parse_ports()
return
if not exists(shared_seafiledir):
os.mkdir(shared_seafiledir)
if not exists(generated_dir):
os.mkdir(generated_dir)
generate_local_dockerfile()
if is_https():
init_letsencrypt()
2016-11-25 06:14:30 +00:00
generate_local_nginx_conf()
2016-11-17 04:40:35 +00:00
init_seafile_server()
2016-11-25 06:14:30 +00:00
show_progress('Generated local config.')
2016-11-17 04:40:35 +00:00
if __name__ == '__main__':
2016-11-16 01:46:08 +00:00
# TODO: validate the content of bootstrap.conf is valid
main()