mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-01 23:20:51 +00:00
new pro scripts
This commit is contained in:
817
scripts/pro.py
Executable file
817
scripts/pro.py
Executable file
@@ -0,0 +1,817 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
'''
|
||||
Setup/Start/Stop the extra components of Seafile Professional
|
||||
|
||||
The diretory layout:
|
||||
- haiwen
|
||||
- seafile-server-1.8.0
|
||||
- seafile.sh
|
||||
- seahub.sh
|
||||
- seafile/
|
||||
- seahub/
|
||||
- pro
|
||||
- pro.py
|
||||
- python
|
||||
- sqlalchemy/
|
||||
- pyes/
|
||||
- thrift/
|
||||
- libevent
|
||||
- python-daemon/
|
||||
- lockfile/
|
||||
- seafes/
|
||||
- seafevents/
|
||||
- seaf-dav/
|
||||
- elasticsearch/
|
||||
- misc
|
||||
- seahub_extra.sql
|
||||
|
||||
- seafile-license.txt
|
||||
- seahub.db
|
||||
- seahub_settings.py
|
||||
- ccnet/
|
||||
- seafile-data/
|
||||
- seahub-data/
|
||||
- pro-data
|
||||
- search/
|
||||
- data/
|
||||
- logs/
|
||||
- seafevents.conf
|
||||
- seafdav.conf
|
||||
- seafevents.db
|
||||
- index.log
|
||||
- seafevents.log
|
||||
'''
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import subprocess
|
||||
import io
|
||||
import getpass
|
||||
|
||||
try:
|
||||
import pymysql
|
||||
except:
|
||||
pass
|
||||
|
||||
import configparser
|
||||
|
||||
########################
|
||||
## Helper functions
|
||||
########################
|
||||
|
||||
class InvalidAnswer(Exception):
|
||||
def __init__(self, msg):
|
||||
Exception.__init__(self)
|
||||
self.msg = msg
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
class Utils(object):
|
||||
'''Groups all helper functions here'''
|
||||
@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, newline=True):
|
||||
sys.stdout.write(msg)
|
||||
if newline:
|
||||
sys.stdout.write('\n')
|
||||
|
||||
@staticmethod
|
||||
def error(msg):
|
||||
'''Print error and exit'''
|
||||
print()
|
||||
print('Error: ' + msg)
|
||||
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()
|
||||
|
||||
@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'''
|
||||
try:
|
||||
os.mkdir(path)
|
||||
except OSError as e:
|
||||
Utils.error('failed to create directory %s:%s' % (path, 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 read_config(fn=None):
|
||||
'''Return a case sensitive ConfigParser by reading the file "fn"'''
|
||||
cp = configparser.ConfigParser()
|
||||
cp.optionxform = str
|
||||
if fn:
|
||||
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
|
||||
print()
|
||||
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:
|
||||
answer = input(desc).strip()
|
||||
|
||||
# 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']:
|
||||
print(Utils.highlight('\nPlease answer yes or no\n'))
|
||||
continue
|
||||
else:
|
||||
return answer == 'yes'
|
||||
else:
|
||||
if validate:
|
||||
try:
|
||||
return validate(answer)
|
||||
except InvalidAnswer as e:
|
||||
print(Utils.highlight('\n%s\n' % e))
|
||||
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
|
||||
|
||||
@staticmethod
|
||||
def get_python_executable():
|
||||
'''Find a suitable python executable'''
|
||||
try_list = [
|
||||
'python3',
|
||||
]
|
||||
|
||||
for prog in try_list:
|
||||
path = Utils.find_in_path(prog)
|
||||
if path is not None:
|
||||
return path
|
||||
|
||||
path = os.environ.get('PYTHON', 'python')
|
||||
|
||||
if not path:
|
||||
Utils.error('Can not find python executable')
|
||||
|
||||
return path
|
||||
|
||||
@staticmethod
|
||||
def pkill(process):
|
||||
'''Kill the program with the given name'''
|
||||
argv = [
|
||||
'pkill', '-f', process
|
||||
]
|
||||
|
||||
Utils.run_argv(argv)
|
||||
|
||||
class EnvManager(object):
|
||||
'''System environment and directory layout'''
|
||||
def __init__(self):
|
||||
self.install_path = os.path.dirname(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')
|
||||
|
||||
self.pro_data_dir = os.path.join(self.top_dir, 'pro-data')
|
||||
self.pro_program_dir = os.path.join(self.install_path, 'pro')
|
||||
self.pro_pylibs_dir = os.path.join(self.pro_program_dir, 'python')
|
||||
self.pro_misc_dir = os.path.join(self.pro_program_dir, 'misc')
|
||||
|
||||
self.seafes_dir = os.path.join(self.pro_pylibs_dir, 'seafes')
|
||||
self.seahub_dir = os.path.join(self.install_path, 'seahub')
|
||||
|
||||
self.ccnet_dir = os.path.join(self.top_dir, 'ccnet')
|
||||
self.seafile_dir = os.path.join(self.top_dir, 'seafile-data')
|
||||
self.central_config_dir = os.path.join(self.top_dir, 'conf')
|
||||
self.seafile_rpc_pipe_path = os.path.join(self.install_path, 'runtime');
|
||||
|
||||
def get_seahub_env(self):
|
||||
'''Prepare for seahub syncdb'''
|
||||
env = dict(os.environ)
|
||||
env['CCNET_CONF_DIR'] = self.ccnet_dir
|
||||
env['SEAFILE_CONF_DIR'] = self.seafile_dir
|
||||
env['SEAFILE_CENTRAL_CONF_DIR'] = self.central_config_dir
|
||||
env['SEAFILE_RPC_PIPE_PATH'] = self.seafile_rpc_pipe_path
|
||||
env['SEAFES_DIR'] = self.seafes_dir
|
||||
env['SEAHUB_DIR'] = self.seahub_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
|
||||
|
||||
'''
|
||||
extra_python_path = [
|
||||
self.pro_pylibs_dir,
|
||||
|
||||
os.path.join(self.top_dir, 'conf'), # LDAP sync has to access seahub_settings.py
|
||||
os.path.join(self.install_path, 'seahub', 'thirdpart'),
|
||||
os.path.join(self.install_path, 'seahub-extra'),
|
||||
os.path.join(self.install_path, 'seahub-extra', 'thirdparts'),
|
||||
|
||||
os.path.join(self.install_path, 'seafile/lib/python3/site-packages'),
|
||||
os.path.join(self.install_path, 'seafile/lib64/python3/site-packages'),
|
||||
]
|
||||
|
||||
for path in extra_python_path:
|
||||
Utils.prepend_env_value('PYTHONPATH', path, env=env)
|
||||
|
||||
########################
|
||||
## END helper functions
|
||||
########################
|
||||
|
||||
class Elasticsearch(object):
|
||||
def __init__(self):
|
||||
self.es_executable = os.path.join(env_mgr.pro_program_dir,
|
||||
'elasticsearch', 'bin', 'elasticsearch')
|
||||
|
||||
self.es_logs_dir = os.path.join(env_mgr.pro_data_dir, 'search', 'logs')
|
||||
self.es_data_dir = os.path.join(env_mgr.pro_data_dir, 'search', 'data')
|
||||
|
||||
def start(self):
|
||||
'''Start Elasticsearch. We use -D command line args to specify the
|
||||
location of logs and data
|
||||
|
||||
'''
|
||||
argv = [
|
||||
self.es_executable,
|
||||
'-Des.path.logs=%s' % self.es_logs_dir,
|
||||
'-Des.path.data=%s' % self.es_data_dir,
|
||||
]
|
||||
Utils.run_argv(argv, suppress_stdout=True, suppress_stderr=True)
|
||||
|
||||
def stop(self):
|
||||
Utils.pkill('org.elasticsearch.bootstrap.ElasticSearch')
|
||||
|
||||
|
||||
class DBConf(object):
|
||||
'''Abstract class for database configuration'''
|
||||
TYPE_SQLITE = 'sqlite'
|
||||
TYPE_MYSQL = 'mysql'
|
||||
|
||||
DB_SECTION = 'DATABASE'
|
||||
def __init__(self, db_type):
|
||||
self.db_type = db_type
|
||||
|
||||
def generate_conf(self, config):
|
||||
raise NotImplementedError
|
||||
|
||||
def create_extra_tables(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def generate_config_text(self):
|
||||
config = Utils.read_config()
|
||||
self.generate_conf(config)
|
||||
|
||||
buf = io.StringIO()
|
||||
config.write(buf)
|
||||
buf.flush()
|
||||
|
||||
return buf.getvalue()
|
||||
|
||||
class MySQLDBConf(DBConf):
|
||||
def __init__(self):
|
||||
DBConf.__init__(self, self.TYPE_MYSQL)
|
||||
|
||||
self.mysql_host = ''
|
||||
self.mysql_port = ''
|
||||
self.mysql_user = ''
|
||||
self.mysql_password = ''
|
||||
self.mysql_db = ''
|
||||
|
||||
self.conn = None
|
||||
|
||||
def generate_conf(self, config):
|
||||
# [DATABASE]
|
||||
# type=mysql
|
||||
# path=x.db
|
||||
# username=seafevents
|
||||
# password=seafevents
|
||||
# name=seafevents
|
||||
# host=localhost
|
||||
config.add_section(self.DB_SECTION)
|
||||
config.set(self.DB_SECTION, 'type', 'mysql')
|
||||
|
||||
if self.mysql_host:
|
||||
config.set(self.DB_SECTION, 'host', self.mysql_host)
|
||||
|
||||
if self.mysql_port:
|
||||
config.set(self.DB_SECTION, 'port', str(self.mysql_port))
|
||||
|
||||
config.set(self.DB_SECTION, 'username', self.mysql_user)
|
||||
config.set(self.DB_SECTION, 'password', self.mysql_password)
|
||||
config.set(self.DB_SECTION, 'name', self.mysql_db)
|
||||
|
||||
def create_extra_tables(self):
|
||||
self.get_conn()
|
||||
sql_file = os.path.join(env_mgr.pro_misc_dir, 'seahub_extra.mysql.sql')
|
||||
with open(sql_file, 'r') as fp:
|
||||
content = fp.read()
|
||||
|
||||
sqls = content.split(';')
|
||||
|
||||
for sql in sqls:
|
||||
sql = sql.strip()
|
||||
if not sql:
|
||||
continue
|
||||
|
||||
print('>>> sql is', sql, len(sql))
|
||||
self.exec_sql(sql)
|
||||
|
||||
def exec_sql(self, sql):
|
||||
cursor = self.conn.cursor()
|
||||
try:
|
||||
cursor.execute(sql)
|
||||
except Exception as e:
|
||||
if isinstance(e, pymysql.err.OperationalError):
|
||||
Utils.error('Failed to create extra tables: %s' % e.args[1])
|
||||
else:
|
||||
Utils.error('Failed to create extra tables: %s' % e)
|
||||
|
||||
def get_conn(self):
|
||||
print('host is', self.mysql_host)
|
||||
print('port is', self.mysql_port)
|
||||
kwargs = dict(user=self.mysql_user,
|
||||
passwd=self.mysql_password,
|
||||
db=self.mysql_db)
|
||||
if self.mysql_port:
|
||||
kwargs['port'] = self.mysql_port
|
||||
if self.mysql_host:
|
||||
kwargs['host'] = self.mysql_host
|
||||
|
||||
try:
|
||||
self.conn = pymysql.connect(**kwargs)
|
||||
except Exception as e:
|
||||
if isinstance(e, pymysql.err.OperationalError):
|
||||
Utils.error('Failed to connect to mysql database %s: %s' % (self.mysql_db, e.args[1]))
|
||||
else:
|
||||
Utils.error('Failed to connect to mysql database %s: %s' % (self.mysql_db, e))
|
||||
|
||||
class SQLiteDBConf(DBConf):
|
||||
def __init__(self):
|
||||
DBConf.__init__(self, self.TYPE_SQLITE)
|
||||
self.db_path = os.path.join(env_mgr.pro_data_dir, 'seafevents.db')
|
||||
|
||||
def generate_conf(self, config):
|
||||
# [DATABASE]
|
||||
# type=sqlite3
|
||||
# path=x.db
|
||||
config.add_section(self.DB_SECTION)
|
||||
config.set(self.DB_SECTION, 'type', 'sqlite3')
|
||||
config.set(self.DB_SECTION, 'path', self.db_path)
|
||||
|
||||
def create_extra_tables(self):
|
||||
seahub_db = os.path.join(env_mgr.top_dir, 'seahub.db')
|
||||
sql_file = os.path.join(env_mgr.pro_misc_dir, 'seahub_extra.sqlite3.sql')
|
||||
|
||||
Utils.info('Create extra database tables ... ', newline=False)
|
||||
cmd = 'sqlite3 %s < %s' % (seahub_db, sql_file)
|
||||
if os.system(cmd) != 0:
|
||||
Utils.error('\nfailed to create seahub extra database tables')
|
||||
Utils.info('Done')
|
||||
|
||||
|
||||
class ProfessionalConfigurator(object):
|
||||
'''Main abstract class for the config process '''
|
||||
def __init__(self, args, migrate=False):
|
||||
self.args = args
|
||||
self.migrate = migrate
|
||||
self.db_type = ''
|
||||
self.db_config = None # database config strategy
|
||||
self.seafevents_conf = os.path.join(env_mgr.central_config_dir, 'seafevents.conf')
|
||||
|
||||
def check_pre_condition(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def config(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def generate(self):
|
||||
self.generate_seafevents_conf()
|
||||
|
||||
def generate_seafevents_conf(self):
|
||||
template = '''\
|
||||
%(db_config_text)s
|
||||
|
||||
[AUDIT]
|
||||
enabled = true
|
||||
|
||||
[INDEX FILES]
|
||||
enabled = true
|
||||
interval = 10m
|
||||
|
||||
highlight = fvh
|
||||
|
||||
## If true, indexes the contents of office/pdf files while updating search index
|
||||
## Note: If you change this option from "false" to "true", then you need to clear the search index and update the index again. See the FAQ for details.
|
||||
index_office_pdf = true
|
||||
|
||||
[SEAHUB EMAIL]
|
||||
enabled = true
|
||||
|
||||
## interval of sending Seahub email. Can be s(seconds), m(minutes), h(hours), d(days)
|
||||
interval = 30m
|
||||
|
||||
# Enable statistics
|
||||
[STATISTICS]
|
||||
enabled=true
|
||||
'''
|
||||
db_config_text = self.db_config.generate_config_text()
|
||||
if not os.path.exists(env_mgr.pro_data_dir):
|
||||
os.makedirs(env_mgr.pro_data_dir)
|
||||
os.chmod(env_mgr.pro_data_dir, 0o700)
|
||||
|
||||
with open(self.seafevents_conf, 'w') as fp:
|
||||
fp.write(template % dict(db_config_text=db_config_text))
|
||||
|
||||
class MigratingProfessionalConfigurator(ProfessionalConfigurator):
|
||||
'''This scripts is used standalone to migrate from community version to
|
||||
professional version
|
||||
|
||||
'''
|
||||
def __init__(self, args):
|
||||
ProfessionalConfigurator.__init__(self, args, migrate=True)
|
||||
|
||||
def check_pre_condition(self):
|
||||
self.check_java()
|
||||
|
||||
def config(self):
|
||||
self.detect_db_type()
|
||||
# self.create_extra_tables()
|
||||
self.update_avatars_link()
|
||||
|
||||
def detect_db_type(self):
|
||||
'''Read database info from seahub_settings.py'''
|
||||
sys.path.insert(0, env_mgr.central_config_dir)
|
||||
try:
|
||||
from seahub_settings import DATABASES # pylint: disable=F0401
|
||||
except ImportError:
|
||||
print('Failed to import "DATABASES" from seahub_settings.py, assuming sqlite3')
|
||||
self.db_config = SQLiteDBConf()
|
||||
return
|
||||
|
||||
try:
|
||||
default_config = DATABASES['default']
|
||||
if default_config['ENGINE'] == 'django.db.backends.mysql':
|
||||
db_config = MySQLDBConf()
|
||||
db_config.mysql_host = default_config.get('HOST', '')
|
||||
db_config.mysql_port = default_config.get('PORT', '')
|
||||
db_config.mysql_user = default_config.get('USER', '')
|
||||
db_config.mysql_password = default_config.get('PASSWORD', '')
|
||||
db_config.mysql_db = default_config['NAME']
|
||||
|
||||
if db_config.mysql_port:
|
||||
db_config.mysql_port = int(db_config.mysql_port)
|
||||
|
||||
print('Your seafile server is using mysql')
|
||||
|
||||
self.db_config = db_config
|
||||
else:
|
||||
print('Your seafile server is using sqlite3')
|
||||
self.db_config = SQLiteDBConf()
|
||||
|
||||
except KeyError:
|
||||
Utils.error('Error in your config %s' % \
|
||||
os.path.join(env_mgr.top_dir, 'seahub_settings.py'))
|
||||
|
||||
def update_avatars_link(self):
|
||||
minor_upgrade_script = os.path.join(env_mgr.install_path, 'upgrade', 'minor-upgrade.sh')
|
||||
argv = [
|
||||
minor_upgrade_script
|
||||
]
|
||||
|
||||
if Utils.run_argv(argv) != 0:
|
||||
Utils.error('failed to update avatars folder')
|
||||
|
||||
def check_java(self):
|
||||
Utils.info('\nChecking java ... ', newline=False)
|
||||
if not Utils.find_in_path('java'):
|
||||
msg = '''\nJava is not found. instal it first.\n
|
||||
On Debian/Ubuntu: apt-get install default-jre
|
||||
On CentOS/RHEL: yum install jre
|
||||
'''
|
||||
Utils.error(msg)
|
||||
|
||||
Utils.info('Done')
|
||||
|
||||
def create_extra_tables(self):
|
||||
'''Create seahub-extra database tables'''
|
||||
self.db_config.create_extra_tables()
|
||||
|
||||
class SetupProfessionalConfigurator(ProfessionalConfigurator):
|
||||
'''This script is invokded by setup-seafile.sh/setup-seafile-mysql.sh to
|
||||
generate seafile pro related conf
|
||||
|
||||
To setup sqlite3:
|
||||
./pro.py setup
|
||||
|
||||
To setup mysql:
|
||||
./pro.py setup --mysql
|
||||
--mysql_host=
|
||||
--mysql_port=
|
||||
--mysql_user=
|
||||
--mysql_password=
|
||||
--mysql_db=
|
||||
|
||||
'''
|
||||
def __init__(self, args):
|
||||
ProfessionalConfigurator.__init__(self, args, migrate=False)
|
||||
|
||||
def config(self):
|
||||
if self.args.mysql:
|
||||
db_config = MySQLDBConf()
|
||||
db_config.mysql_host = self.args.mysql_host
|
||||
db_config.mysql_port = self.args.mysql_port
|
||||
db_config.mysql_user = self.args.mysql_user
|
||||
db_config.mysql_password = self.args.mysql_password
|
||||
db_config.mysql_db = self.args.mysql_db
|
||||
else:
|
||||
db_config = SQLiteDBConf()
|
||||
|
||||
self.db_config = db_config
|
||||
|
||||
def check_pre_condition(self):
|
||||
pass
|
||||
|
||||
def do_setup(args):
|
||||
global pro_config
|
||||
|
||||
if args.migrate:
|
||||
pro_config = MigratingProfessionalConfigurator(args)
|
||||
else:
|
||||
pro_config = SetupProfessionalConfigurator(args)
|
||||
|
||||
pro_config.check_pre_condition()
|
||||
pro_config.config()
|
||||
pro_config.generate()
|
||||
|
||||
def handle_search_commands(args):
|
||||
'''provide search related utility'''
|
||||
if args.update:
|
||||
update_search_index()
|
||||
elif args.clear:
|
||||
delete_search_index()
|
||||
|
||||
def get_seafes_env():
|
||||
env = env_mgr.get_seahub_env()
|
||||
events_conf = os.path.join(env_mgr.central_config_dir, 'seafevents.conf')
|
||||
|
||||
env['EVENTS_CONFIG_FILE'] = events_conf
|
||||
|
||||
return env
|
||||
|
||||
def update_search_index():
|
||||
argv = [
|
||||
Utils.get_python_executable(),
|
||||
'-m', 'seafes.index_local',
|
||||
'--loglevel', 'debug',
|
||||
'update',
|
||||
]
|
||||
|
||||
Utils.info('\nUpdating search index, this may take a while...\n')
|
||||
|
||||
Utils.run_argv(argv, env=get_seafes_env())
|
||||
|
||||
def delete_search_index():
|
||||
choice = None
|
||||
while choice not in ('y', 'n', ''):
|
||||
prompt = 'Delete seafile search index ([y]/n)? '
|
||||
choice = input(prompt).strip()
|
||||
|
||||
if choice == 'n':
|
||||
return
|
||||
|
||||
argv = [
|
||||
Utils.get_python_executable(),
|
||||
'-m', 'seafes.index_local',
|
||||
'--loglevel', 'debug',
|
||||
'clear',
|
||||
]
|
||||
|
||||
Utils.info('\nDelete search index, this may take a while...\n')
|
||||
|
||||
Utils.run_argv(argv, env=get_seafes_env())
|
||||
|
||||
def handle_ldap_sync_commands(args):
|
||||
if args.test:
|
||||
argv = [
|
||||
Utils.get_python_executable(),
|
||||
'-m', 'seafevents.ldap_syncer.run_ldap_sync',
|
||||
'-t',
|
||||
]
|
||||
else:
|
||||
argv = [
|
||||
Utils.get_python_executable(),
|
||||
'-m', 'seafevents.ldap_syncer.run_ldap_sync',
|
||||
]
|
||||
|
||||
Utils.run_argv(argv, env=env_mgr.get_seahub_env())
|
||||
|
||||
def handle_virus_scan_commands(args):
|
||||
argv = [
|
||||
Utils.get_python_executable(),
|
||||
'-m', 'seafevents.virus_scanner.run_virus_scan',
|
||||
'-c', os.path.join(env_mgr.central_config_dir, 'seafevents.conf'),
|
||||
]
|
||||
|
||||
Utils.run_argv(argv, env=env_mgr.get_seahub_env())
|
||||
|
||||
pro_config = None
|
||||
env_mgr = EnvManager()
|
||||
|
||||
def main():
|
||||
try:
|
||||
import argparse
|
||||
except ImportError:
|
||||
sys.path.insert(0, glob.glob(os.path.join(env_mgr.pro_pylibs_dir, 'argparse*.egg'))[0])
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
subparsers = parser.add_subparsers(title='subcommands', description='')
|
||||
|
||||
# setup
|
||||
parser_setup = subparsers.add_parser('setup', help='Setup extra components of seafile pro')
|
||||
parser_setup.set_defaults(func=do_setup)
|
||||
parser_setup.add_argument('--migrate', help='migrate from community version', action='store_true')
|
||||
|
||||
# for non-migreate setup
|
||||
parser_setup.add_argument('--mysql', help='use mysql', action='store_true')
|
||||
parser_setup.add_argument('--mysql_host')
|
||||
parser_setup.add_argument('--mysql_port')
|
||||
parser_setup.add_argument('--mysql_user')
|
||||
parser_setup.add_argument('--mysql_password')
|
||||
parser_setup.add_argument('--mysql_db')
|
||||
|
||||
# search
|
||||
parser_search = subparsers.add_parser('search', help='search related utility commands')
|
||||
parser_search.add_argument('--update', help='update seafile search index', action='store_true')
|
||||
parser_search.add_argument('--clear', help='delete seafile search index', action='store_true')
|
||||
parser_search.set_defaults(func=handle_search_commands)
|
||||
|
||||
# ldapsync
|
||||
parser_ldap_sync = subparsers.add_parser('ldapsync', help='ldap sync commands')
|
||||
parser_ldap_sync.add_argument('-t', '--test', help='test ldap sync', action='store_true')
|
||||
parser_ldap_sync.set_defaults(func=handle_ldap_sync_commands)
|
||||
|
||||
# virus scan
|
||||
parser_virus_scan = subparsers.add_parser('virus_scan', help='virus scan commands')
|
||||
parser_virus_scan.set_defaults(func=handle_virus_scan_commands)
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
print(parser.format_help())
|
||||
return
|
||||
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Reference in New Issue
Block a user