1
0
mirror of https://github.com/haiwen/seafile-server.git synced 2025-05-08 08:06:22 +00:00
seafile-server/scripts/setup-seafile-mysql.py

1586 lines
56 KiB
Python
Raw Normal View History

2016-08-10 06:53:33 +00:00
#coding: UTF-8
'''This script would guide the seafile admin to setup seafile with MySQL'''
2017-01-07 03:20:18 +00:00
import argparse
2016-08-10 06:53:33 +00:00
import sys
import os
import time
import re
import shutil
import glob
import subprocess
import hashlib
import getpass
import uuid
import warnings
import socket
2019-06-28 05:30:31 +00:00
from configparser import ConfigParser
2016-08-10 06:53:33 +00:00
2019-08-16 04:11:18 +00:00
import pymysql
2017-01-07 03:20:18 +00:00
2016-08-10 06:53:33 +00:00
try:
import readline # pylint: disable=W0611
except ImportError:
pass
2019-12-02 09:05:15 +00:00
SERVER_MANUAL_HTTP = 'https://download.seafile.com/published/seafile-manual/home.md'
2016-08-10 06:53:33 +00:00
class Utils(object):
'''Groups all helper functions here'''
@staticmethod
def welcome():
'''Show welcome message'''
welcome_msg = '''\
-----------------------------------------------------------------
This script will guide you to setup your seafile server using MySQL.
Make sure you have read seafile server manual at
%s
Press ENTER to continue
-----------------------------------------------------------------''' % SERVER_MANUAL_HTTP
2019-06-28 05:30:31 +00:00
print(welcome_msg)
input()
2016-08-10 06:53:33 +00:00
@staticmethod
def highlight(content):
'''Add ANSI color to content to get it highlighted on terminal'''
return '\x1b[33m%s\x1b[m' % content
@staticmethod
def info(msg):
2019-06-28 05:30:31 +00:00
print(msg)
2016-08-10 06:53:33 +00:00
@staticmethod
def error(msg):
'''Print error and exit'''
2019-06-28 05:30:31 +00:00
print()
print('Error: ' + msg)
2016-08-10 06:53:33 +00:00
sys.exit(1)
@staticmethod
def run_argv(argv, cwd=None, env=None, suppress_stdout=False, suppress_stderr=False):
'''Run a program and wait it to finish, and return its exit code. The
standard output of this program is supressed.
'''
with open(os.devnull, 'w') as devnull:
if suppress_stdout:
stdout = devnull
else:
stdout = sys.stdout
if suppress_stderr:
stderr = devnull
else:
stderr = sys.stderr
proc = subprocess.Popen(argv,
cwd=cwd,
stdout=stdout,
stderr=stderr,
env=env)
return proc.wait()
@staticmethod
def run(cmdline, cwd=None, env=None, suppress_stdout=False, suppress_stderr=False):
'''Like run_argv but specify a command line string instead of argv'''
with open(os.devnull, 'w') as devnull:
if suppress_stdout:
stdout = devnull
else:
stdout = sys.stdout
if suppress_stderr:
stderr = devnull
else:
stderr = sys.stderr
proc = subprocess.Popen(cmdline,
cwd=cwd,
stdout=stdout,
stderr=stderr,
env=env,
shell=True)
return proc.wait()
2017-01-07 04:23:08 +00:00
@staticmethod
def get_command_output(args, *a, **kw):
return subprocess.check_output(args, *a, **kw)
2016-08-10 06:53:33 +00:00
@staticmethod
def prepend_env_value(name, value, env=None, seperator=':'):
'''prepend a new value to a list'''
if env is None:
env = os.environ
try:
current_value = env[name]
except KeyError:
current_value = ''
new_value = value
if current_value:
new_value += seperator + current_value
env[name] = new_value
@staticmethod
def must_mkdir(path):
'''Create a directory, exit on failure'''
if os.path.exists(path):
return
try:
os.mkdir(path)
2019-06-28 05:30:31 +00:00
except OSError as e:
2016-08-10 06:53:33 +00:00
Utils.error('failed to create directory %s:%s' % (path, e))
@staticmethod
def must_copy(src, dst):
'''Copy src to dst, exit on failure'''
try:
shutil.copy(src, dst)
2019-06-28 05:30:31 +00:00
except Exception as e:
2016-08-10 06:53:33 +00:00
Utils.error('failed to copy %s to %s: %s' % (src, dst, e))
@staticmethod
def find_in_path(prog):
if 'win32' in sys.platform:
sep = ';'
else:
sep = ':'
dirs = os.environ['PATH'].split(sep)
for d in dirs:
d = d.strip()
if d == '':
continue
path = os.path.join(d, prog)
if os.path.exists(path):
return path
return None
@staticmethod
def get_python_executable():
'''Return the python executable. This should be the PYTHON environment
variable which is set in setup-seafile-mysql.sh
'''
return os.environ['PYTHON']
@staticmethod
def read_config(fn):
'''Return a case sensitive ConfigParser by reading the file "fn"'''
cp = ConfigParser()
cp.optionxform = str
cp.read(fn)
return cp
@staticmethod
def write_config(cp, fn):
'''Return a case sensitive ConfigParser by reading the file "fn"'''
with open(fn, 'w') as fp:
cp.write(fp)
@staticmethod
def ask_question(desc,
key=None,
note=None,
default=None,
validate=None,
yes_or_no=False,
password=False):
'''Ask a question, return the answer.
@desc description, e.g. "What is the port of ccnet?"
@key a name to represent the target of the question, e.g. "port for
ccnet server"
@note additional information for the question, e.g. "Must be a valid
port number"
@default the default value of the question. If the default value is
not None, when the user enter nothing and press [ENTER], the default
value would be returned
@validate a function that takes the user input as the only parameter
and validate it. It should return a validated value, or throws an
"InvalidAnswer" exception if the input is not valid.
@yes_or_no If true, the user must answer "yes" or "no", and a boolean
value would be returned
@password If true, the user input would not be echoed to the
console
'''
assert key or yes_or_no
# Format description
2019-06-28 05:30:31 +00:00
print()
2016-08-10 06:53:33 +00:00
if note:
desc += '\n' + note
desc += '\n'
if yes_or_no:
desc += '[ yes or no ]'
else:
if default:
desc += '[ default "%s" ]' % default
else:
desc += '[ %s ]' % key
desc += ' '
while True:
# prompt for user input
if password:
answer = getpass.getpass(desc).strip()
else:
2019-06-28 05:30:31 +00:00
answer = input(desc).strip()
2016-08-10 06:53:33 +00:00
# No user input: use default
if not answer:
if default:
answer = default
else:
continue
# Have user input: validate answer
if yes_or_no:
if answer not in ['yes', 'no']:
2019-06-28 05:30:31 +00:00
print(Utils.highlight('\nPlease answer yes or no\n'))
2016-08-10 06:53:33 +00:00
continue
else:
return answer == 'yes'
else:
if validate:
try:
return validate(answer)
2019-06-28 05:30:31 +00:00
except InvalidAnswer as e:
print(Utils.highlight('\n%s\n' % e))
2016-08-10 06:53:33 +00:00
continue
else:
return answer
@staticmethod
def validate_port(port):
try:
port = int(port)
except ValueError:
raise InvalidAnswer('%s is not a valid port' % Utils.highlight(port))
if port <= 0 or port > 65535:
raise InvalidAnswer('%s is not a valid port' % Utils.highlight(port))
return port
class InvalidAnswer(Exception):
def __init__(self, msg):
Exception.__init__(self)
self.msg = msg
def __str__(self):
return self.msg
class InvalidParams(Exception):
def __init__(self, msg):
Exception.__init__(self)
self.msg = msg
def __str__(self):
return self.msg
### END of Utils
####################
class EnvManager(object):
'''System environment and directory layout'''
def __init__(self):
self.install_path = os.path.dirname(os.path.abspath(__file__))
self.top_dir = os.path.dirname(self.install_path)
self.bin_dir = os.path.join(self.install_path, 'seafile', 'bin')
self.central_config_dir = os.path.join(self.top_dir, 'conf')
2018-04-18 10:10:28 +00:00
self.central_pids_dir = os.path.join(self.top_dir, 'pids')
self.central_logs_dir = os.path.join(self.top_dir, 'logs')
2016-08-10 06:53:33 +00:00
Utils.must_mkdir(self.central_config_dir)
def check_pre_condiction(self):
def error_if_not_exists(path):
if not os.path.exists(path):
Utils.error('"%s" not found' % path)
paths = [
os.path.join(self.install_path, 'seafile'),
os.path.join(self.install_path, 'seahub'),
os.path.join(self.install_path, 'runtime'),
]
for path in paths:
error_if_not_exists(path)
if os.path.exists(ccnet_config.ccnet_dir):
Utils.error('Ccnet config dir \"%s\" already exists.' % ccnet_config.ccnet_dir)
def get_seahub_env(self):
'''Prepare for seahub syncdb'''
env = dict(os.environ)
env['CCNET_CONF_DIR'] = ccnet_config.ccnet_dir
env['SEAFILE_CONF_DIR'] = seafile_config.seafile_dir
self.setup_python_path(env)
return env
def setup_python_path(self, env):
'''And PYTHONPATH and CCNET_CONF_DIR/SEAFILE_CONF_DIR to env, which is
needed by seahub
'''
install_path = self.install_path
pro_pylibs_dir = os.path.join(install_path, 'pro', 'python')
extra_python_path = [
pro_pylibs_dir,
os.path.join(install_path, 'seahub', 'thirdpart'),
2019-08-16 04:11:18 +00:00
os.path.join(install_path, 'seafile/lib/python3.6/site-packages'),
os.path.join(install_path, 'seafile/lib64/python3.6/site-packages'),
2016-08-10 06:53:33 +00:00
]
for path in extra_python_path:
Utils.prepend_env_value('PYTHONPATH', path, env=env)
def get_binary_env(self):
'''Set LD_LIBRARY_PATH for seafile server executables'''
env = dict(os.environ)
lib_dir = os.path.join(self.install_path, 'seafile', 'lib')
lib64_dir = os.path.join(self.install_path, 'seafile', 'lib64')
Utils.prepend_env_value('LD_LIBRARY_PATH', lib_dir, env=env)
Utils.prepend_env_value('LD_LIBRARY_PATH', lib64_dir, env=env)
return env
class AbstractConfigurator(object):
'''Abstract Base class for ccnet/seafile/seahub/db configurator'''
def __init__(self):
pass
def ask_questions(self):
raise NotImplementedError
def generate(self):
raise NotImplementedError
class AbstractDBConfigurator(AbstractConfigurator):
'''Abstract class for database related configuration'''
def __init__(self):
AbstractConfigurator.__init__(self)
self.mysql_host = 'localhost'
self.mysql_port = 3306
2019-12-02 09:34:35 +00:00
self.unix_socket = "/var/run/mysqld/mysqld.sock"
2016-08-10 06:53:33 +00:00
self.use_existing_db = False
self.seafile_mysql_user = ''
self.seafile_mysql_password = ''
self.seafile_mysql_userhost = '127.0.0.1'
2016-08-10 06:53:33 +00:00
2017-01-07 03:20:18 +00:00
self.root_password = ''
self.root_conn = ''
2016-08-10 06:53:33 +00:00
self.ccnet_db_name = ''
self.seafile_db_name = ''
self.seahub_db_name = ''
self.seahub_admin_email = ''
self.seahub_admin_password = ''
@staticmethod
def ask_use_existing_db():
def validate(choice):
if choice not in ['1', '2']:
raise InvalidAnswer('Please choose 1 or 2')
return choice == '2'
question = '''\
-------------------------------------------------------
Please choose a way to initialize seafile databases:
-------------------------------------------------------
'''
note = '''\
[1] Create new ccnet/seafile/seahub databases
[2] Use existing ccnet/seafile/seahub databases
'''
return Utils.ask_question(question,
key='1 or 2',
note=note,
validate=validate)
def validate_mysql_host(self, host):
if not re.match(r'^[a-zA-Z0-9_\-\.]+$', host):
raise InvalidAnswer('%s is not a valid host' % Utils.highlight(host))
if host == 'localhost':
host = '127.0.0.1'
return host
def ask_mysql_host(self):
question = 'What is the host of mysql server?'
key = 'mysql server host'
default = 'localhost'
self.mysql_host = Utils.ask_question(question,
key=key,
default=default,
validate=self.validate_mysql_host)
def validate_mysql_user_host(self, host):
MYSQL_HOST_RE = re.compile(r'^(%|[^.].+\..+[^.])$')
if not MYSQL_HOST_RE.match(host):
raise InvalidAnswer('invalid mysql user host: {}'.format(host))
return host
def ask_mysql_user_host(self):
self.seafile_mysql_userhost = Utils.ask_question(
'From which hosts could the mysql account be used?',
key='mysql user host',
default='%',
validate=self.validate_mysql_user_host
)
def ask_mysql_port(self):
question = 'What is the port of mysql server?'
key = 'mysql server port'
default = '3306'
port = Utils.ask_question(question,
key=key,
default=default,
validate=Utils.validate_port)
# self.check_mysql_server(host, port)
self.mysql_port = port
def ask_mysql_host_port(self):
self.ask_mysql_host()
if self.mysql_host != '127.0.0.1':
self.ask_mysql_user_host()
self.ask_mysql_port()
def check_mysql_server(self, host, port):
2019-06-28 05:30:31 +00:00
print('\nverifying mysql server running ... ', end=' ')
2016-08-10 06:53:33 +00:00
try:
2019-08-16 04:11:18 +00:00
dummy = pymysql.connect(host=host, port=port)
2016-08-10 06:53:33 +00:00
except Exception:
2019-06-28 05:30:31 +00:00
print()
2016-08-10 06:53:33 +00:00
raise InvalidAnswer('Failed to connect to mysql server at "%s:%s"' \
% (host, port))
2019-06-28 05:30:31 +00:00
print('done')
2016-08-10 06:53:33 +00:00
2019-12-02 06:56:57 +00:00
def check_mysql_user(self, user, password, host=None, unix_socket=None):
2019-06-28 05:30:31 +00:00
print('\nverifying password of user %s ... ' % user, end=' ')
2019-12-02 08:37:20 +00:00
kwargs = dict(port=self.mysql_port,
2016-08-10 06:53:33 +00:00
user=user,
2019-12-02 08:37:20 +00:00
passwd=password)
if unix_socket:
kwargs['unix_socket'] = unix_socket
else:
kwargs['host'] = host or self.mysql_host
2016-08-10 06:53:33 +00:00
try:
2019-08-16 04:11:18 +00:00
conn = pymysql.connect(**kwargs)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
raise InvalidAnswer('Failed to connect to mysql server using user "%s" and password "***": %s' \
% (user, e.args[1]))
else:
raise InvalidAnswer('Failed to connect to mysql server using user "%s" and password "***": %s' \
% (user, e))
2019-06-28 05:30:31 +00:00
print('done')
2016-08-10 06:53:33 +00:00
return conn
def create_seahub_admin(self):
try:
2019-08-16 04:11:18 +00:00
conn = pymysql.connect(host=self.mysql_host,
2016-08-10 06:53:33 +00:00
port=self.mysql_port,
user=self.seafile_mysql_user,
passwd=self.seafile_mysql_password,
db=self.ccnet_db_name)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
Utils.error('Failed to connect to mysql database %s: %s' % (self.ccnet_db_name, e.args[1]))
else:
Utils.error('Failed to connect to mysql database %s: %s' % (self.ccnet_db_name, e))
cursor = conn.cursor()
sql = '''\
CREATE TABLE IF NOT EXISTS EmailUser (id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, email VARCHAR(255), passwd CHAR(64), is_staff BOOL NOT NULL, is_active BOOL NOT NULL, ctime BIGINT, UNIQUE INDEX (email)) ENGINE=INNODB'''
try:
cursor.execute(sql)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
Utils.error('Failed to create ccnet user table: %s' % e.args[1])
else:
Utils.error('Failed to create ccnet user table: %s' % e)
sql = '''REPLACE INTO EmailUser(email, passwd, is_staff, is_active, ctime) VALUES ('%s', '%s', 1, 1, 0)''' \
% (seahub_config.admin_email, seahub_config.hashed_admin_password())
try:
cursor.execute(sql)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
Utils.error('Failed to create admin user: %s' % e.args[1])
else:
Utils.error('Failed to create admin user: %s' % e)
conn.commit()
def ask_questions(self):
'''Ask questions and do database operations'''
raise NotImplementedError
class NewDBConfigurator(AbstractDBConfigurator):
'''Handles the case of creating new mysql databases for ccnet/seafile/seahub'''
def __init__(self):
AbstractDBConfigurator.__init__(self)
def ask_questions(self):
self.ask_mysql_host_port()
self.ask_root_password()
self.ask_seafile_mysql_user_password()
self.ask_db_names()
def generate(self):
if not self.mysql_user_exists(self.seafile_mysql_user):
self.create_user()
self.create_databases()
def validate_root_passwd(self, password):
try:
self.root_conn = self.check_mysql_user('root', password)
except InvalidAnswer:
# For MariaDB on Ubuntu 16.04, the msyql root user can only be
# accessed from localhost with unix socket. So we retry with
# localhost when failing with 127.0.0.1.
if self.mysql_host == '127.0.0.1':
2019-12-02 09:34:35 +00:00
self.root_conn = self.check_mysql_user('root', password, unix_socket=self.unix_socket)
else:
raise
2016-08-10 06:53:33 +00:00
return password
def ask_root_password(self):
question = 'What is the password of the mysql root user?'
key = 'root password'
self.root_password = Utils.ask_question(question,
key=key,
validate=self.validate_root_passwd,
password=True)
def mysql_user_exists(self, user):
cursor = self.root_conn.cursor()
sql = '''SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '%s' and host = '%s')''' % \
(user, self.seafile_mysql_userhost)
try:
cursor.execute(sql)
return cursor.fetchall()[0][0]
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
Utils.error('Failed to check mysql user %s@%s: %s' % \
(user, self.seafile_mysql_userhost, e.args[1]))
else:
Utils.error('Failed to check mysql user %s@%s: %s' % \
(user, self.seafile_mysql_userhost, e))
finally:
cursor.close()
def ask_seafile_mysql_user_password(self):
def validate(user):
if user == 'root':
raise InvalidAnswer(
'Using mysql "root" user is not allowed for security reasons. Please specify a different database user.'
)
2016-08-10 06:53:33 +00:00
else:
question = 'Enter the password for mysql user "%s":' % Utils.highlight(user)
key = 'password for %s' % user
password = Utils.ask_question(question, key=key, password=True)
# If the user already exists, check the password here
if self.mysql_user_exists(user):
self.check_mysql_user(user, password)
self.seafile_mysql_password = password
return user
question = 'Enter the name for mysql user of seafile. It would be created if not exists.'
key = 'mysql user for seafile'
default = 'seafile'
2016-08-10 06:53:33 +00:00
self.seafile_mysql_user = Utils.ask_question(question,
key=key,
default=default,
validate=validate)
def ask_db_name(self, program, default):
question = 'Enter the database name for %s:' % program
key = '%s database' % program
return Utils.ask_question(question,
key=key,
default=default,
validate=self.validate_db_name)
def ask_db_names(self):
self.ccnet_db_name = self.ask_db_name('ccnet-server', 'ccnet-db')
self.seafile_db_name = self.ask_db_name('seafile-server', 'seafile-db')
self.seahub_db_name = self.ask_db_name('seahub', 'seahub-db')
def validate_db_name(self, db_name):
return db_name
def create_user(self):
cursor = self.root_conn.cursor()
sql = '''CREATE USER '{}'@'{}' IDENTIFIED BY '{}' '''.format(
self.seafile_mysql_user,
self.seafile_mysql_userhost,
self.seafile_mysql_password
)
try:
cursor.execute(sql)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
Utils.error('Failed to create mysql user {}@{}: {}'.format(self.seafile_mysql_user, self.seafile_mysql_userhost, e.args[1]))
else:
Utils.error('Failed to create mysql user {}@{}: {}'.format(self.seafile_mysql_user, self.seafile_mysql_userhost, e))
finally:
cursor.close()
def create_db(self, db_name):
cursor = self.root_conn.cursor()
sql = '''CREATE DATABASE IF NOT EXISTS `%s` CHARACTER SET UTF8''' \
% db_name
try:
cursor.execute(sql)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
Utils.error('Failed to create database %s: %s' % (db_name, e.args[1]))
else:
Utils.error('Failed to create database %s: %s' % (db_name, e))
finally:
cursor.close()
def grant_db_permission(self, db_name):
cursor = self.root_conn.cursor()
sql = '''GRANT ALL PRIVILEGES ON `{}`.* to `{}`@`{}` '''.format(
db_name,
self.seafile_mysql_user,
self.seafile_mysql_userhost
)
try:
cursor.execute(sql)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
Utils.error('Failed to grant permission of database %s: %s' % (db_name, e.args[1]))
else:
Utils.error('Failed to grant permission of database %s: %s' % (db_name, e))
finally:
cursor.close()
def create_databases(self):
self.create_db(self.ccnet_db_name)
self.create_db(self.seafile_db_name)
self.create_db(self.seahub_db_name)
if self.seafile_mysql_user != 'root':
self.grant_db_permission(self.ccnet_db_name)
self.grant_db_permission(self.seafile_db_name)
self.grant_db_permission(self.seahub_db_name)
class ExistingDBConfigurator(AbstractDBConfigurator):
'''Handles the case of use existing mysql databases for ccnet/seafile/seahub'''
def __init__(self):
AbstractDBConfigurator.__init__(self)
self.use_existing_db = True
def ask_questions(self):
self.ask_mysql_host_port()
self.ask_existing_mysql_user_password()
self.ccnet_db_name = self.ask_db_name('ccnet')
self.seafile_db_name = self.ask_db_name('seafile')
self.seahub_db_name = self.ask_db_name('seahub')
def generate(self):
pass
def ask_existing_mysql_user_password(self):
def validate(user):
if user == 'root':
raise InvalidAnswer(
'Using root is not allowed for security reasons. Please specify a different database user.'
)
2016-08-10 06:53:33 +00:00
question = 'What is the password for mysql user "%s"?' % Utils.highlight(user)
key = 'password for %s' % user
password = Utils.ask_question(question, key=key, password=True)
self.check_mysql_user(user, password)
self.seafile_mysql_password = password
return user
question = 'Which mysql user to use for seafile?'
key = 'mysql user for seafile'
self.seafile_mysql_user = Utils.ask_question(question,
key=key,
validate=validate)
def validate_db_name(self, db_name):
self.check_user_db_access(db_name)
return db_name
def ask_db_name(self, program):
question = 'Enter the existing database name for %s:' % program
key = '%s database' % program
return Utils.ask_question(question,
key=key,
validate=self.validate_db_name)
def check_user_db_access(self, db_name):
user = self.seafile_mysql_user
password = self.seafile_mysql_password
2019-06-28 05:30:31 +00:00
print('\nverifying user "%s" access to database %s ... ' % (user, db_name), end=' ')
2016-08-10 06:53:33 +00:00
try:
2019-08-16 04:11:18 +00:00
conn = pymysql.connect(host=self.mysql_host,
2016-08-10 06:53:33 +00:00
port=self.mysql_port,
user=user,
passwd=password,
db=db_name)
cursor = conn.cursor()
cursor.execute('show tables')
cursor.close()
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
raise InvalidAnswer('Failed to access database %s using user "%s" and password "***": %s' \
% (db_name, user, e.args[1]))
else:
raise InvalidAnswer('Failed to access database %s using user "%s" and password "***": %s' \
% (db_name, user, e))
2019-06-28 05:30:31 +00:00
print('done')
2016-08-10 06:53:33 +00:00
return conn
class CcnetConfigurator(AbstractConfigurator):
SERVER_NAME_REGEX = r'^[a-zA-Z0-9_\-]{3,15}$'
SERVER_IP_OR_DOMAIN_REGEX = r'^[^.].+\..+[^.]$'
def __init__(self):
'''Initialize default values of ccnet configuration'''
AbstractConfigurator.__init__(self)
self.ccnet_dir = os.path.join(env_mgr.top_dir, 'ccnet')
self.port = 10001
self.server_name = None
self.ip_or_domain = None
self.ccnet_conf = os.path.join(env_mgr.central_config_dir, 'ccnet.conf')
def ask_questions(self):
if not self.server_name:
self.ask_server_name()
if not self.ip_or_domain:
self.ask_server_ip_or_domain()
# self.ask_port()
def generate(self):
2019-06-28 05:30:31 +00:00
print('Generating ccnet configuration ...\n')
2016-08-10 06:53:33 +00:00
ccnet_init = os.path.join(env_mgr.bin_dir, 'ccnet-init')
argv = [
ccnet_init,
'-F', env_mgr.central_config_dir,
'--config-dir', self.ccnet_dir,
'--host', self.ip_or_domain,
]
if Utils.run_argv(argv, env=env_mgr.get_binary_env()) != 0:
Utils.error('Failed to generate ccnet configuration')
time.sleep(1)
self.generate_db_conf()
def generate_db_conf(self):
config = Utils.read_config(self.ccnet_conf)
# [Database]
# ENGINE=
# HOST=
# USER=
# PASSWD=
# DB=
db_section = 'Database'
if not config.has_section(db_section):
config.add_section(db_section)
config.set(db_section, 'ENGINE', 'mysql')
config.set(db_section, 'HOST', db_config.mysql_host)
2019-08-16 04:11:18 +00:00
config.set(db_section, 'PORT', str(db_config.mysql_port))
2016-08-10 06:53:33 +00:00
config.set(db_section, 'USER', db_config.seafile_mysql_user)
config.set(db_section, 'PASSWD', db_config.seafile_mysql_password)
config.set(db_section, 'DB', db_config.ccnet_db_name)
config.set(db_section, 'CONNECTION_CHARSET', 'utf8')
Utils.write_config(config, self.ccnet_conf)
def validate_server_name(self, name):
if not re.match(self.SERVER_NAME_REGEX, name):
raise InvalidAnswer('%s is not a valid name' % Utils.highlight(name))
return name
def ask_server_name(self):
question = 'What is the name of the server? It will be displayed on the client.'
key = 'server name'
note = '3 - 15 letters or digits'
self.server_name = Utils.ask_question(question,
key=key,
note=note,
validate=self.validate_server_name)
def validate_server_ip(self, ip_or_domain):
if not re.match(self.SERVER_IP_OR_DOMAIN_REGEX, ip_or_domain):
raise InvalidAnswer('%s is not a valid ip or domain' % ip_or_domain)
return ip_or_domain
def ask_server_ip_or_domain(self):
question = 'What is the ip or domain of the server?'
key = 'This server\'s ip or domain'
note = 'For example: www.mycompany.com, 192.168.1.101'
self.ip_or_domain = Utils.ask_question(question,
key=key,
note=note,
validate=self.validate_server_ip)
def ask_port(self):
def validate(port):
return Utils.validate_port(port)
question = 'Which port do you want to use for the ccnet server?'
key = 'ccnet server port'
default = 10001
self.port = Utils.ask_question(question,
key=key,
default=default,
validate=validate)
2019-03-27 08:14:00 +00:00
def do_syncdb(self):
2019-06-28 05:30:31 +00:00
print('----------------------------------------')
print('Now creating ccnet database tables ...\n')
print('----------------------------------------')
2019-03-27 08:14:00 +00:00
try:
2019-08-16 04:11:18 +00:00
conn = pymysql.connect(host=db_config.mysql_host,
2019-03-27 08:14:00 +00:00
port=db_config.mysql_port,
user=db_config.seafile_mysql_user,
passwd=db_config.seafile_mysql_password,
db=db_config.ccnet_db_name)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2019-03-27 08:14:00 +00:00
Utils.error('Failed to connect to mysql database %s: %s' % (db_config.ccnet_db_name, e.args[1]))
else:
Utils.error('Failed to connect to mysql database %s: %s' % (db_config.ccnet_db_name, e))
cursor = conn.cursor()
sql_file = os.path.join(env_mgr.install_path, 'sql', 'mysql', 'ccnet.sql')
with open(sql_file, 'r') as fp:
content = fp.read()
sqls = [line.strip() for line in content.split(';') if line.strip()]
for sql in sqls:
try:
cursor.execute(sql)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2019-03-27 08:14:00 +00:00
Utils.error('Failed to init ccnet database: %s' % e.args[1])
else:
Utils.error('Failed to init ccnet database: %s' % e)
conn.commit()
2016-08-10 06:53:33 +00:00
class SeafileConfigurator(AbstractConfigurator):
def __init__(self):
AbstractConfigurator.__init__(self)
self.seafile_dir = None
self.port = 12001
self.fileserver_port = None
self.seafile_conf = os.path.join(env_mgr.central_config_dir, 'seafile.conf')
def ask_questions(self):
if not self.seafile_dir:
self.ask_seafile_dir()
# self.ask_port()
if not self.fileserver_port:
self.ask_fileserver_port()
def generate(self):
2019-06-28 05:30:31 +00:00
print('Generating seafile configuration ...\n')
2016-08-10 06:53:33 +00:00
seafserv_init = os.path.join(env_mgr.bin_dir, 'seaf-server-init')
argv = [
seafserv_init,
'-F', env_mgr.central_config_dir,
'--seafile-dir', self.seafile_dir,
'--fileserver-port', str(self.fileserver_port),
]
if Utils.run_argv(argv, env=env_mgr.get_binary_env()) != 0:
Utils.error('Failed to generate ccnet configuration')
time.sleep(1)
self.generate_db_conf()
self.write_seafile_ini()
2019-06-28 05:30:31 +00:00
print('done')
2016-08-10 06:53:33 +00:00
def generate_db_conf(self):
config = Utils.read_config(self.seafile_conf)
# [database]
# type=
# host=
# user=
# password=
# db_name=
# unix_socket=
db_section = 'database'
if not config.has_section(db_section):
config.add_section(db_section)
config.set(db_section, 'type', 'mysql')
config.set(db_section, 'host', db_config.mysql_host)
2019-08-16 04:11:18 +00:00
config.set(db_section, 'port', str(db_config.mysql_port))
2016-08-10 06:53:33 +00:00
config.set(db_section, 'user', db_config.seafile_mysql_user)
config.set(db_section, 'password', db_config.seafile_mysql_password)
config.set(db_section, 'db_name', db_config.seafile_db_name)
config.set(db_section, 'connection_charset', 'utf8')
Utils.write_config(config, self.seafile_conf)
def validate_seafile_dir(self, path):
if os.path.exists(path):
raise InvalidAnswer('%s already exists' % Utils.highlight(path))
return path
def ask_seafile_dir(self):
question = 'Where do you want to put your seafile data?'
key = 'seafile-data'
note = 'Please use a volume with enough free space'
default = os.path.join(env_mgr.top_dir, 'seafile-data')
self.seafile_dir = Utils.ask_question(question,
key=key,
note=note,
default=default,
validate=self.validate_seafile_dir)
def ask_port(self):
def validate(port):
port = Utils.validate_port(port)
if port == ccnet_config.port:
raise InvalidAnswer('%s is used by ccnet server, choose another one' \
% Utils.highlight(port))
return port
question = 'Which port do you want to use for the seafile server?'
key = 'seafile server port'
default = 12001
self.port = Utils.ask_question(question,
key=key,
default=default,
validate=validate)
def ask_fileserver_port(self):
question = 'Which port do you want to use for the seafile fileserver?'
key = 'seafile fileserver port'
default = 8082
self.fileserver_port = Utils.ask_question(question,
key=key,
default=default,
validate=Utils.validate_port)
def write_seafile_ini(self):
seafile_ini = os.path.join(ccnet_config.ccnet_dir, 'seafile.ini')
with open(seafile_ini, 'w') as fp:
fp.write(self.seafile_dir)
2019-03-27 08:14:00 +00:00
def do_syncdb(self):
2019-06-28 05:30:31 +00:00
print('----------------------------------------')
print('Now creating seafile database tables ...\n')
print('----------------------------------------')
2019-03-27 08:14:00 +00:00
try:
2019-08-16 04:11:18 +00:00
conn = pymysql.connect(host=db_config.mysql_host,
2019-03-27 08:14:00 +00:00
port=db_config.mysql_port,
user=db_config.seafile_mysql_user,
passwd=db_config.seafile_mysql_password,
db=db_config.seafile_db_name)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2019-03-27 08:14:00 +00:00
Utils.error('Failed to connect to mysql database %s: %s' % (db_config.seafile_db_name, e.args[1]))
else:
Utils.error('Failed to connect to mysql database %s: %s' % (db_config.seafile_db_name, e))
cursor = conn.cursor()
sql_file = os.path.join(env_mgr.install_path, 'sql', 'mysql', 'seafile.sql')
with open(sql_file, 'r') as fp:
content = fp.read()
sqls = [line.strip() for line in content.split(';') if line.strip()]
for sql in sqls:
try:
cursor.execute(sql)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2019-03-27 08:14:00 +00:00
Utils.error('Failed to init seafile database: %s' % e.args[1])
else:
Utils.error('Failed to init seafile database: %s' % e)
conn.commit()
2016-08-10 06:53:33 +00:00
class SeahubConfigurator(AbstractConfigurator):
def __init__(self):
AbstractConfigurator.__init__(self)
self.admin_email = ''
self.admin_password = ''
self.seahub_settings_py = os.path.join(env_mgr.central_config_dir, 'seahub_settings.py')
def hashed_admin_password(self):
return hashlib.sha1(self.admin_password).hexdigest() # pylint: disable=E1101
def ask_questions(self):
pass
def generate(self):
'''Generating seahub_settings.py'''
2019-06-28 05:30:31 +00:00
print('Generating seahub configuration ...\n')
2016-08-10 06:53:33 +00:00
time.sleep(1)
with open(self.seahub_settings_py, 'w') as fp:
self.write_utf8_comment(fp)
fp.write('\n')
self.write_secret_key(fp)
fp.write('\n')
2016-08-10 06:53:33 +00:00
self.write_database_config(fp)
def write_utf8_comment(self, fp):
fp.write('# -*- coding: utf-8 -*-')
def write_secret_key(self, fp):
script = os.path.join(env_mgr.install_path, 'seahub/tools/secret_key_generator.py')
cmd = [
Utils.get_python_executable(),
script,
]
key = Utils.get_command_output(cmd).strip()
fp.write('SECRET_KEY = "%s"' % key)
2016-08-10 06:53:33 +00:00
def write_database_config(self, fp):
template = '''\
\nDATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '%(name)s',
'USER': '%(username)s',
'PASSWORD': '%(password)s',
'HOST': '%(host)s',
'PORT': '%(port)s'
}
}
'''
text = template % dict(name=db_config.seahub_db_name,
username=db_config.seafile_mysql_user,
password=db_config.seafile_mysql_password,
host=db_config.mysql_host,
port=db_config.mysql_port)
fp.write(text)
def ask_admin_email(self):
2019-06-28 05:30:31 +00:00
print()
print('----------------------------------------')
print('Now let\'s create the admin account')
print('----------------------------------------')
2016-08-10 06:53:33 +00:00
def validate(email):
# whitespace is not allowed
if re.match(r'[\s]', email):
raise InvalidAnswer('%s is not a valid email address' % Utils.highlight(email))
# must be a valid email address
if not re.match(r'^.+@.*\..+$', email):
raise InvalidAnswer('%s is not a valid email address' % Utils.highlight(email))
return email
key = 'admin email'
question = 'What is the ' + Utils.highlight('email') + ' for the admin account?'
self.admin_email = Utils.ask_question(question,
key=key,
validate=validate)
def ask_admin_password(self):
def validate(password):
key = 'admin password again'
question = 'Enter the ' + Utils.highlight('password again:')
password_again = Utils.ask_question(question,
key=key,
password=True)
if password_again != password:
raise InvalidAnswer('password mismatch')
return password
key = 'admin password'
question = 'What is the ' + Utils.highlight('password') + ' for the admin account?'
self.admin_password = Utils.ask_question(question,
key=key,
password=True,
validate=validate)
def do_syncdb(self):
2019-06-28 05:30:31 +00:00
print('----------------------------------------')
print('Now creating seahub database tables ...\n')
print('----------------------------------------')
2016-08-10 06:53:33 +00:00
try:
2019-08-16 04:11:18 +00:00
conn = pymysql.connect(host=db_config.mysql_host,
2016-08-10 06:53:33 +00:00
port=db_config.mysql_port,
user=db_config.seafile_mysql_user,
passwd=db_config.seafile_mysql_password,
db=db_config.seahub_db_name)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
Utils.error('Failed to connect to mysql database %s: %s' % (db_config.seahub_db_name, e.args[1]))
else:
Utils.error('Failed to connect to mysql database %s: %s' % (db_config.seahub_db_name, e))
cursor = conn.cursor()
sql_file = os.path.join(env_mgr.install_path, 'seahub', 'sql', 'mysql.sql')
with open(sql_file, 'r') as fp:
content = fp.read()
sqls = [line.strip() for line in content.split(';') if line.strip()]
for sql in sqls:
try:
cursor.execute(sql)
2019-06-28 05:30:31 +00:00
except Exception as e:
2019-08-16 04:11:18 +00:00
if isinstance(e, pymysql.err.OperationalError):
2016-08-10 06:53:33 +00:00
Utils.error('Failed to init seahub database: %s' % e.args[1])
else:
Utils.error('Failed to init seahub database: %s' % e)
conn.commit()
def prepare_avatar_dir(self):
# media_dir=${INSTALLPATH}/seahub/media
# orig_avatar_dir=${INSTALLPATH}/seahub/media/avatars
# dest_avatar_dir=${TOPDIR}/seahub-data/avatars
# if [[ ! -d ${dest_avatar_dir} ]]; then
# mkdir -p "${TOPDIR}/seahub-data"
# mv "${orig_avatar_dir}" "${dest_avatar_dir}"
# ln -s ../../../seahub-data/avatars ${media_dir}
# fi
try:
media_dir = os.path.join(env_mgr.install_path, 'seahub', 'media')
orig_avatar_dir = os.path.join(media_dir, 'avatars')
seahub_data_dir = os.path.join(env_mgr.top_dir, 'seahub-data')
dest_avatar_dir = os.path.join(seahub_data_dir, 'avatars')
if os.path.exists(dest_avatar_dir):
return
if not os.path.exists(seahub_data_dir):
os.mkdir(seahub_data_dir)
shutil.move(orig_avatar_dir, dest_avatar_dir)
os.symlink('../../../seahub-data/avatars', orig_avatar_dir)
2019-06-28 05:30:31 +00:00
except Exception as e:
2016-08-10 06:53:33 +00:00
Utils.error('Failed to prepare seahub avatars dir: %s' % e)
class SeafDavConfigurator(AbstractConfigurator):
def __init__(self):
AbstractConfigurator.__init__(self)
self.seafdav_conf = None
def ask_questions(self):
pass
def generate(self):
self.seafdav_conf = os.path.join(env_mgr.central_config_dir, 'seafdav.conf')
text = '''
[WEBDAV]
enabled = false
port = 8080
fastcgi = false
share_name = /
'''
with open(self.seafdav_conf, 'w') as fp:
fp.write(text)
2018-04-18 10:10:28 +00:00
class GunicornConfigurator(AbstractConfigurator):
def __init__(self):
AbstractConfigurator.__init__(self)
self.gunicorn_conf = None
def ask_questions(self):
pass
def generate(self):
self.gunicorn_conf = os.path.join(env_mgr.central_config_dir, 'gunicorn.conf')
template = '''
import os
daemon = True
workers = 5
# default localhost:8000
bind = "127.0.0.1:8000"
2018-04-18 10:10:28 +00:00
# Pid
pids_dir = '%(pids_dir)s'
pidfile = os.path.join(pids_dir, 'seahub.pid')
# for file upload, we need a longer timeout value (default is only 30s, too short)
timeout = 1200
limit_request_line = 8190
2018-04-18 10:10:28 +00:00
'''
text = template % dict(pids_dir=env_mgr.central_pids_dir,
logs_dir=env_mgr.central_logs_dir)
with open(self.gunicorn_conf, 'w') as fp:
fp.write(text)
2016-08-10 06:53:33 +00:00
class UserManualHandler(object):
def __init__(self):
self.src_docs_dir = os.path.join(env_mgr.install_path, 'seafile', 'docs')
self.library_template_dir = None
def copy_user_manuals(self):
self.library_template_dir = os.path.join(seafile_config.seafile_dir, 'library-template')
Utils.must_mkdir(self.library_template_dir)
pattern = os.path.join(self.src_docs_dir, '*.doc')
for doc in glob.glob(pattern):
Utils.must_copy(doc, self.library_template_dir)
def report_config():
2019-06-28 05:30:31 +00:00
print()
print('---------------------------------')
print('This is your configuration')
print('---------------------------------')
print()
2016-08-10 06:53:33 +00:00
template = '''\
server name: %(server_name)s
server ip/domain: %(ip_or_domain)s
seafile data dir: %(seafile_dir)s
fileserver port: %(fileserver_port)s
database: %(use_existing_db)s
ccnet database: %(ccnet_db_name)s
seafile database: %(seafile_db_name)s
seahub database: %(seahub_db_name)s
database user: %(db_user)s
'''
config = {
'server_name' : ccnet_config.server_name,
'ip_or_domain' : ccnet_config.ip_or_domain,
'seafile_dir' : seafile_config.seafile_dir,
'fileserver_port' : seafile_config.fileserver_port,
'admin_email' : seahub_config.admin_email,
'use_existing_db': 'use existing' if db_config.use_existing_db else 'create new',
'ccnet_db_name': db_config.ccnet_db_name,
'seafile_db_name': db_config.seafile_db_name,
'seahub_db_name': db_config.seahub_db_name,
'db_user': db_config.seafile_mysql_user
}
2019-06-28 05:30:31 +00:00
print(template % config)
2016-08-10 06:53:33 +00:00
if need_pause:
2019-06-28 05:30:31 +00:00
print()
print('---------------------------------')
print('Press ENTER to continue, or Ctrl-C to abort')
print('---------------------------------')
2016-08-10 06:53:33 +00:00
2019-06-28 05:30:31 +00:00
input()
2016-08-10 06:53:33 +00:00
def create_seafile_server_symlink():
2019-06-28 05:30:31 +00:00
print('\ncreating seafile-server-latest symbolic link ... ', end=' ')
2016-08-10 06:53:33 +00:00
seafile_server_symlink = os.path.join(env_mgr.top_dir, 'seafile-server-latest')
try:
os.symlink(os.path.basename(env_mgr.install_path), seafile_server_symlink)
2019-06-28 05:30:31 +00:00
except Exception as e:
print('\n')
2016-08-10 06:53:33 +00:00
Utils.error('Failed to create symbolic link %s: %s' % (seafile_server_symlink, e))
else:
2019-06-28 05:30:31 +00:00
print('done\n\n')
2016-08-10 06:53:33 +00:00
def set_file_perm():
2019-06-28 05:30:31 +00:00
filemode = 0o600
dirmode = 0o700
2016-08-10 06:53:33 +00:00
files = [
seahub_config.seahub_settings_py,
]
dirs = [
env_mgr.central_config_dir,
ccnet_config.ccnet_dir,
seafile_config.seafile_dir,
seahub_config.seahub_settings_py,
]
for fpath in files:
os.chmod(fpath, filemode)
for dpath in dirs:
os.chmod(dpath, dirmode)
env_mgr = EnvManager()
ccnet_config = CcnetConfigurator()
seafile_config = SeafileConfigurator()
seafdav_config = SeafDavConfigurator()
2018-04-18 10:10:28 +00:00
gunicorn_config = GunicornConfigurator()
2016-08-10 06:53:33 +00:00
seahub_config = SeahubConfigurator()
user_manuals_handler = UserManualHandler()
# Would be created after AbstractDBConfigurator.ask_use_existing_db()
db_config = None
need_pause = True
def get_param_val(arg, env, default=None):
return arg or os.environ.get(env, default)
def check_params(args):
server_name = 'seafile'
2016-08-10 06:53:33 +00:00
ccnet_config.server_name = ccnet_config.validate_server_name(server_name)
server_ip = get_param_val(args.server_ip, 'SERVER_IP', '127.0.0.1')
2016-08-10 06:53:33 +00:00
ccnet_config.ip_or_domain = ccnet_config.validate_server_ip(server_ip)
fileserver_port = get_param_val(args.fileserver_port, 'FILESERVER_PORT', '8082')
seafile_config.fileserver_port = Utils.validate_port(fileserver_port)
seafile_dir = get_param_val(args.seafile_dir, 'SEAFILE_DIR',
os.path.join(env_mgr.top_dir, 'seafile-data'))
seafile_config.seafile_dir = seafile_config.validate_seafile_dir(seafile_dir)
global db_config
use_existing_db = get_param_val(args.use_existing_db, 'USE_EXISTING_DB', '0')
2017-01-07 03:20:18 +00:00
# pylint: disable=redefined-variable-type
2016-08-10 06:53:33 +00:00
if use_existing_db == '0':
db_config = NewDBConfigurator()
elif use_existing_db == '1':
db_config = ExistingDBConfigurator()
else:
raise InvalidParams('Invalid use existing db parameter, the value can only be 0 or 1')
mysql_host = get_param_val(args.mysql_host, 'MYSQL_HOST', '127.0.0.1')
if not mysql_host:
raise InvalidParams('Incomplete mysql configuration parameters, ' \
'missing mysql host parameter')
db_config.mysql_host = db_config.validate_mysql_host(mysql_host)
mysql_port = get_param_val(args.mysql_port, 'MYSQL_PORT', '3306')
db_config.mysql_port = Utils.validate_port(mysql_port)
mysql_user = get_param_val(args.mysql_user, 'MYSQL_USER')
if not mysql_user:
raise InvalidParams('Incomplete mysql configuration parameters, ' \
'missing mysql user name parameter')
mysql_user_passwd = get_param_val(args.mysql_user_passwd, 'MYSQL_USER_PASSWD')
if not mysql_user_passwd:
raise InvalidParams('Incomplete mysql configuration parameters, ' \
'missing mysql user password parameter')
ccnet_db = get_param_val(args.ccnet_db, 'CCNET_DB', 'ccnet_db')
if not ccnet_db:
raise InvalidParams('Incomplete mysql configuration parameters, ' \
'missing ccnet db name parameter')
seafile_db = get_param_val(args.seafile_db, 'SEAFILE_DB', 'seafile_db')
if not seafile_db:
raise InvalidParams('Incomplete mysql configuration parameters, ' \
'missing seafile db name parameter')
seahub_db = get_param_val(args.seahub_db, 'SEAHUB_DB', 'seahub_db')
if not seahub_db:
raise InvalidParams('Incomplete mysql configuration parameters, ' \
'missing seahub db name parameter')
mysql_user_host = get_param_val(args.mysql_user_host, 'MYSQL_USER_HOST')
mysql_root_passwd = get_param_val(args.mysql_root_passwd, 'MYSQL_ROOT_PASSWD')
if db_config.use_existing_db:
db_config.check_mysql_user(mysql_user, mysql_user_passwd)
db_config.seafile_mysql_user = mysql_user
db_config.seafile_mysql_password = mysql_user_passwd
db_config.ccnet_db_name = db_config.validate_db_name(ccnet_db)
db_config.seafile_db_name = db_config.validate_db_name(seafile_db)
db_config.seahub_db_name = db_config.validate_db_name(seahub_db)
else:
if db_config.mysql_host != '127.0.0.1' and not mysql_user_host:
raise InvalidParams('mysql user host parameter is missing in creating new db mode')
if not mysql_user_host:
db_config.seafile_mysql_userhost = '127.0.0.1'
2016-08-10 06:53:33 +00:00
else:
db_config.seafile_mysql_userhost = db_config.validate_mysql_user_host(mysql_user_host)
if not mysql_root_passwd and "MYSQL_ROOT_PASSWD" not in os.environ:
2016-08-10 06:53:33 +00:00
raise InvalidParams('mysql root password parameter is missing in creating new db mode')
db_config.root_password = db_config.validate_root_passwd(mysql_root_passwd)
if mysql_user == 'root':
db_config.seafile_mysql_user = 'root'
db_config.seafile_mysql_password = db_config.root_password
else:
if db_config.mysql_user_exists(mysql_user):
db_config.check_mysql_user(mysql_user, mysql_user_passwd)
db_config.seafile_mysql_user = mysql_user
db_config.seafile_mysql_password = mysql_user_passwd
db_config.ccnet_db_name = ccnet_db
db_config.seafile_db_name = seafile_db
db_config.seahub_db_name = seahub_db
global need_pause
need_pause = False
def main():
if len(sys.argv) > 2 and sys.argv[1] == 'auto':
sys.argv.remove('auto')
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--server-name', help='server name')
parser.add_argument('-i', '--server-ip', help='server ip or domain')
parser.add_argument('-p', '--fileserver-port', help='fileserver port')
parser.add_argument('-d', '--seafile-dir', help='seafile dir to store seafile data')
parser.add_argument('-e', '--use-existing-db',
help='use mysql existing dbs or create new dbs, '
'0: create new dbs 1: use existing dbs')
parser.add_argument('-o', '--mysql-host', help='mysql host')
parser.add_argument('-t', '--mysql-port', help='mysql port')
parser.add_argument('-u', '--mysql-user', help='mysql user name')
parser.add_argument('-w', '--mysql-user-passwd', help='mysql user password')
parser.add_argument('-q', '--mysql-user-host', help='mysql user host')
parser.add_argument('-r', '--mysql-root-passwd', help='mysql root password')
parser.add_argument('-c', '--ccnet-db', help='ccnet db name')
parser.add_argument('-s', '--seafile-db', help='seafile db name')
parser.add_argument('-b', '--seahub-db', help='seahub db name')
args = parser.parse_args()
try:
check_params(args)
except (InvalidAnswer, InvalidParams) as e:
2019-06-28 05:30:31 +00:00
print(Utils.highlight('\n%s\n' % e))
2016-08-10 06:53:33 +00:00
sys.exit(-1)
global db_config
if need_pause:
Utils.welcome()
2019-08-16 04:11:18 +00:00
warnings.filterwarnings('ignore', category=pymysql.Warning)
2016-08-10 06:53:33 +00:00
env_mgr.check_pre_condiction()
# Part 1: collect configuration
ccnet_config.ask_questions()
seafile_config.ask_questions()
seahub_config.ask_questions()
2017-01-07 03:20:18 +00:00
# pylint: disable=redefined-variable-type
2016-08-10 06:53:33 +00:00
if not db_config:
if AbstractDBConfigurator.ask_use_existing_db():
db_config = ExistingDBConfigurator()
else:
db_config = NewDBConfigurator()
db_config.ask_questions()
report_config()
# Part 2: generate configuration
db_config.generate()
ccnet_config.generate()
seafile_config.generate()
seafdav_config.generate()
2018-04-18 10:10:28 +00:00
gunicorn_config.generate()
2016-08-10 06:53:33 +00:00
seahub_config.generate()
2019-03-27 08:14:00 +00:00
ccnet_config.do_syncdb()
seafile_config.do_syncdb()
2016-08-10 06:53:33 +00:00
seahub_config.do_syncdb()
seahub_config.prepare_avatar_dir()
# db_config.create_seahub_admin()
user_manuals_handler.copy_user_manuals()
create_seafile_server_symlink()
set_file_perm()
report_success()
def report_success():
message = '''\
-----------------------------------------------------------------
Your seafile server configuration has been finished successfully.
-----------------------------------------------------------------
run seafile server: ./seafile.sh { start | stop | restart }
run seahub server: ./seahub.sh { start <port> | stop | restart <port> }
-----------------------------------------------------------------
If you are behind a firewall, remember to allow input/output of these tcp ports:
-----------------------------------------------------------------
port of seafile fileserver: %(fileserver_port)s
port of seahub: 8000
When problems occur, Refer to
%(server_manual_http)s
for information.
'''
2019-06-28 05:30:31 +00:00
print(message % dict(fileserver_port=seafile_config.fileserver_port,
server_manual_http=SERVER_MANUAL_HTTP))
2016-08-10 06:53:33 +00:00
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
2019-06-28 05:30:31 +00:00
print()
print(Utils.highlight('The setup process is aborted'))
print()