#!/usr/bin/env python
# coding: UTF-8

'''This is the helper script to setup/manage your seafile server
'''

import sys

####################
### Requires Python 2.6+
####################
if sys.version_info.major == 3:
    print 'Python 3 not supported yet. Quit now'
    sys.exit(1)
if sys.version_info.minor < 6:
    print 'Python 2.6 or above is required. Quit now'
    sys.exit(1)

import os
import time
import re
import shutil
import subprocess
import argparse
import uuid

try:
    import readline
    # Avoid pylint 'unused import' warning
    dummy = readline
except ImportError:
    pass

####################
### Cosntants
####################
SERVER_MANUAL_HTTP = 'https://github.com/haiwen/seafile/wiki'
SEAFILE_GOOGLE_GROUP = 'https://groups.google.com/forum/?fromgroups#!forum/seafile'
SEAFILE_WEBSITE = 'http://www.seafile.com'
SEAHUB_DOWNLOAD_URL = 'https://seafile.com.cn/downloads/seahub-latest.tar.gz'

####################
### Global variables
####################
cwd = os.getcwd()
SCRIPT_NAME = os.path.basename(sys.argv[0])

PYTHON = sys.executable

conf = {}
CONF_SERVER_NAME = 'server_name'
CONF_CCNET_DIR = 'ccnet_dir'
CONF_SEAFILE_DIR = 'seafile_dir'
CONF_SEAHUB_DIR = 'seafile_dir'
CONF_CCNET_PORT = 'ccnet_port'
CONF_SEAFILE_PORT = 'seafile_port'
CONF_FILESERVER_PORT = 'fileserver_port'
CONF_IP_OR_DOMAIN = 'ip_or_domain'

CONF_SEAHUB_CONF = 'seahub_conf'
CONF_SEAHUB_DIR = 'seahub_dir'
CONF_SEAHUB_PORT = 'seahub_port'

CONF_SEAHUB_PIDFILE = 'seahub_pidfile'
CONF_SEAHUB_OUTLOG = 'seahub_outlog'
CONF_SEAHUB_ERRLOG = 'seahub_errlog'

CONF_CCNET_CONF_EXISTS = 'ccnet_conf_exists'
CONF_SEAFILE_CONF_EXISTS = 'seafile_conf_exists'

CONF_ADMIN_EMAIL = 'admin_email'
CONF_ADMIN_PASSWORD = 'admin_password'

####################
### Common helper functions

def highlight(content):
    '''Add ANSI color to content to get it highlighted on terminal'''
    return '\x1b[33m%s\x1b[m' % content

def info(msg):
    print msg

def error(msg):
    print 'Error: ' + msg
    sys.exit(1)

def ask_question(desc, key=None, note=None, default=None,
                 validate=None, yes_or_no=False, invalidate_msg=None):
    '''Ask a question, return the answer. The optional validate param is a
    function used to validate the answer. If yes_or_no is True, then a boolean
    value would be returned.

    '''
    assert key or yes_or_no
    desc = highlight(desc)
    if note:
        desc += '  (%s)' % note
    if default:
        desc += '\n' + ('[default %s ]' % default)
    else:
        if yes_or_no:
            desc += '\n[yes or no]'
        else:
            desc += '\n' + ('[%s ]' % key)

    desc += '  '
    while True:
        answer = raw_input(desc)
        if not answer:
            if default:
                print ''
                return default
            else:
                continue

        answer = answer.strip()

        if yes_or_no:
            if answer != 'yes' and answer != 'no':
                print '\nPlease answer yes or no\n'
                continue
            else:
                return answer == 'yes'
        else:
            if validate and not validate(answer):
                if invalidate_msg:
                    print '\n%s\n' % invalidate_msg
                else:
                    print '\n"%s" is not a valid %s\n' % (answer, key)
                continue

        print ''
        return answer

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()

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()

def is_running(process):
    '''Detect if there is a process with the given name running'''
    argv = [
        'pgrep', '-f', process
    ]

    return run_argv(argv, suppress_stdout=True) == 0

def pkill(process):
    '''Kill the program with the given name'''
    argv = [
        'pkill', '-f', process
    ]

    run_argv(argv)

def kill(pid):
    '''Kill the program with the given pid'''
    argv = [
        'kill', pid
    ]

    run_argv(argv)

def must_mkdir(path):
    '''Create a directory, exit on failure'''
    try:
        os.mkdir(path)
    except OSError, e:
        error('failed to create directory %s:%s' % (path, e))

### END of Common helper functions
####################

def check_seafile_install():
    '''Check if seafile has been correctly built and installed in this
    system

    '''
    dirs = os.environ['PATH'].split(':')
    def exist_in_path(prog):
        '''Test whether prog exists in system path'''
        for d in dirs:
            if d == '':
                continue
            path = os.path.join(d, prog)
            if os.path.exists(path):
                return True

        return False

    def check_prog(name):
        if not exist_in_path(name):
            error('%s not found in PATH. Have you built and installed seafile server?' % name)

    progs = [
        'ccnet-init',
        'seaf-server-init',
        'seaf-server',
        'ccnet-server',
        'seafile-controller',
    ]

    for prog in progs:
        check_prog(prog)

def get_seahub_env():
    '''And PYTHONPATH and CCNET_CONF_DIR/SEAFILE_CONF_DIR to env, which is
    needed by seahub

    '''
    seahub_dir = conf[CONF_SEAHUB_DIR]
    seahub_thirdpart_dir = os.path.join(seahub_dir, 'thirdpart')

    env = dict(os.environ)
    pypath = env.get('PYTHONPATH', '')

    pathlist = [ p for p in pypath.split(':') if p != '' ]
    pathlist.append(seahub_thirdpart_dir)
    newpypath = ':'.join(pathlist)
    env['PYTHONPATH'] = newpypath
    env['CCNET_CONF_DIR'] = conf[CONF_CCNET_DIR]
    env['SEAFILE_CONF_DIR'] = conf[CONF_SEAFILE_DIR]
    return env


####################
### <setup> command
####################
def welcome():
    '''Show welcome message when running the <setup> command'''
    welcome_msg = '''\
-----------------------------------------------------------------
This script will guide you to config and setup your seafile server.
Make sure you have read seafile server manual at

        %s

Press [ENTER] to continue
-----------------------------------------------------------------
''' % SERVER_MANUAL_HTTP
    print welcome_msg
    raw_input()

def get_server_name():
    def validate(name):
        r = re.compile(r'^[\w]{3,15}$')
        return bool(r.match(name))
    question = 'What is the name of the server?'
    key = 'server name'
    note = '3 - 15 letters or digits'
    conf[CONF_SERVER_NAME] = ask_question(question,
                                          key=key,
                                          note=note,
                                          validate=validate)

def get_server_ip_or_domain():
    def validate(s):
        r = r'^[^.].+\..+[^.]$'
        return bool(re.match(r, s))
    question = 'What is the ip of the server?'
    key = 'ip or domain'
    note = 'For example: www.mycompany.com, 192.168.1.101'
    conf[CONF_IP_OR_DOMAIN] = ask_question(question,
                                           key=key,
                                           note=note,
                                           validate=validate)
def get_ccnet_conf_dir():
    ccnet_conf_dir = os.path.join(cwd, 'ccnet')
    ccnet_conf = os.path.join(ccnet_conf_dir, 'ccnet.conf')

    if os.path.exists(ccnet_conf_dir):
        if os.path.exists(ccnet_conf):
            question = 'It seems there already exists ccnet config files in %s, Do you want to use them?' % ccnet_conf_dir
            yesno = ask_question(question, yes_or_no=True)
            if not yesno:
                print highlight('\nRemove the directory %s first, and run the script again.\n' % ccnet_conf_dir)
                sys.exit(1)
            else:
                conf[CONF_CCNET_CONF_EXISTS] = True
        else:
            print 'Please remove the directory %s first, and run the script again' % ccnet_conf_dir
    else:
        conf[CONF_CCNET_CONF_EXISTS] = False

    conf[CONF_CCNET_DIR] = ccnet_conf_dir

def get_ccnet_port():
    def validate(s):
        try:
            port = int(s)
        except ValueError:
            return False

        return port > 0 and port < 65536

    question = 'Which port do you want to use for the ccnet server?'
    key = 'ccnet server port'
    default = '10001'
    conf[CONF_CCNET_PORT] = ask_question(question,
                                         key=key,
                                         default=default,
                                         validate=validate)

def get_seafile_port():
    def validate(s):
        try:
            port = int(s)
        except ValueError:
            return False

        return port > 0 and port < 65536

    question = 'Which port do you want to use for the seafile server?'
    key = 'seafile server port'
    default = '12001'
    conf[CONF_SEAFILE_PORT] = ask_question(question,
                                           key=key,
                                           default=default,
                                           validate=validate)

def get_fileserver_port():
    def validate(s):
        try:
            port = int(s)
        except ValueError:
            return False

        return port > 0 and port < 65536

    question = 'Which port do you want to use for the seafile fileserver?'
    key = 'seafile fileserver port'
    default = '8082'
    conf[CONF_FILESERVER_PORT] = ask_question(question,
                                              key=key,
                                              default=default,
                                              validate=validate)
def get_seafile_data_dir():
    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(cwd, 'seafile-data')
    seafile_data_dir = ask_question(question,
                                    key=key,
                                    note=note,
                                    default=default)
    seafile_conf = os.path.join(seafile_data_dir, 'seafile.conf')

    if os.path.exists(seafile_data_dir):
        if os.path.exists(seafile_conf):
            question = 'It seems there already exists seafile data in %s, Do you want to use them?' % seafile_data_dir
            yesno = ask_question(question, yes_or_no=True)
            if not yesno:
                print highlight('\nRemove the directory %s first, and run the script again.\n' % seafile_data_dir)
                sys.exit(1)
            else:
                conf[CONF_SEAFILE_CONF_EXISTS] = True
        else:
            info('Please remove the directory %s first, and run the script again' % seafile_data_dir)
    else:
        conf[CONF_SEAFILE_CONF_EXISTS] = False

    conf[CONF_SEAFILE_DIR] = seafile_data_dir


def create_gunicorn_conf():
    runtime_dir = os.path.join(cwd, 'seafile-server', 'runtime')
    confpath = os.path.join(runtime_dir, 'seahub.conf')

    if os.path.exists(confpath):
        return

    if not os.path.exists(runtime_dir):
        must_mkdir(runtime_dir)

    content = '''\
import os
daemon = True
workers = 3

# Logging
runtime_dir = os.path.dirname(__file__)
pidfile = os.path.join(runtime_dir, 'seahub.pid')
errorlog = os.path.join(runtime_dir, 'error.log')
accesslog = os.path.join(runtime_dir, 'access.log')
'''
    try:
        with open(confpath, 'w') as fp:
            fp.write(content)
    except:
        error('Failed to write seahub config')

def gen_seahub_secret_key():
    data = str(uuid.uuid4()) + str(uuid.uuid4())
    return data[:40]

def create_seahub_settings_py():
    seahub_settings_py = os.path.join(cwd, 'seahub_settings.py')
    try:
        with open(seahub_settings_py, 'w') as fp:
            line = "SECRET_KEY = '%s'" % gen_seahub_secret_key()
            fp.write(line)
    except Exception, e:
        error('failed to create %s: %s' % (seahub_settings_py, e))

def move_avatar():
    seahub_data_dir = os.path.join(cwd, 'seahub-data')
    outside_avatar_dir = os.path.join(seahub_data_dir, 'avatars')
    seahub_avatar_dir = os.path.join(conf[CONF_SEAHUB_DIR], 'media', 'avatars')

    if os.path.exists(outside_avatar_dir):
        return

    if not os.path.exists(seahub_data_dir):
        must_mkdir(seahub_data_dir)

    # move the avatars dir outside
    shutil.move(seahub_avatar_dir, outside_avatar_dir)
    # make the the original avatars dir a symlink pointing to the outside dir
    os.symlink(outside_avatar_dir, seahub_avatar_dir)

def init_seahub():
    seahub_dir = conf[CONF_SEAHUB_DIR]

    # create seahub_settings.py
    create_seahub_settings_py()

    argv = [PYTHON, 'manage.py', 'syncdb']
    # Set proper PYTHONPATH before run django syncdb command
    env = get_seahub_env()

    print
    print
    info('Now initializing seahub database, please wait...')
    print

    if run_argv(argv, cwd=seahub_dir, env=env) != 0:
        error('Seahub syncdb failed')

    info('done')

    move_avatar()
    create_gunicorn_conf()

def check_django_version():
    '''Requires django 1.5'''
    import django
    if django.VERSION[1] != 5:
        error('Django 1.5 is required')
    else:
        del django

def check_python_module(import_name, package_name, silent=False):
    if not silent:
        info('checking %s' % package_name)
    try:
        __import__(import_name)
    except ImportError:
        error('Python module "%s" not found. Please install it first' % package_name)

def check_python_dependencies(silent=False):
    '''Ensure all python libraries we need are installed'''

    if not silent:
        info('check python modules ...')
    check_python_module('sqlite3', 'sqlite3', silent=silent)
    check_python_module('PIL', 'python imaging library(PIL)', silent=silent)
    check_python_module('django', 'django 1.5', silent=silent)
    check_python_module('djblets', 'djblets', silent=silent)
    check_django_version()

    print

def config_ccnet_seafile():
    get_ccnet_conf_dir()
    if not conf[CONF_CCNET_CONF_EXISTS]:
        get_server_name()
        get_server_ip_or_domain()
        get_ccnet_port()

    get_seafile_data_dir()
    if not conf[CONF_SEAFILE_CONF_EXISTS]:
        get_seafile_port()
        get_fileserver_port()

    info('This is your configuration')
    info('------------------------------------------')
    if conf[CONF_CCNET_CONF_EXISTS]:
        info('ccnet config:        use existing config in %s' % highlight(conf[CONF_CCNET_DIR]))
    else:
        info('ccnet conf dir:           %s' % highlight(conf[CONF_CCNET_DIR]))
        info('server name:              %s' % highlight(conf[CONF_SERVER_NAME]))
        info('server host:              %s' % highlight(conf[CONF_IP_OR_DOMAIN]))
        info('ccnet port:               %s' % highlight(conf[CONF_CCNET_PORT]))

    if conf[CONF_SEAFILE_CONF_EXISTS]:
        info('seafile:             use existing config in %s' % highlight(conf[CONF_SEAFILE_DIR]))
    else:
        info('seafile data dir:         %s' % highlight(conf[CONF_SEAFILE_DIR]))
        info('seafile port:             %s' % highlight(conf[CONF_SEAFILE_PORT]))
        info('seafile fileserver port:  %s' % highlight(conf[CONF_FILESERVER_PORT]))

    info('------------------------------------------')
    info('Press ENTER if the config is right, or anything else to re-config ')

    if raw_input() != '':
        config_ccnet_seafile()
    else:
        return

def init_ccnet_seafile():
    if not conf[CONF_CCNET_CONF_EXISTS]:
        info('Generating ccnet configuration...')
        argv = [
            'ccnet-init',
            '-c', conf[CONF_CCNET_DIR],
            '--name', conf[CONF_SERVER_NAME],
            '--port', conf[CONF_CCNET_PORT],
            '--host', conf[CONF_IP_OR_DOMAIN],
        ]

        if run_argv(argv) != 0:
            error('failed to init ccnet configuration')

        info('done')

    if not conf[CONF_SEAFILE_CONF_EXISTS]:
        info('Generating seafile configuration...')
        argv = [
            'seaf-server-init',
            '--seafile-dir', conf[CONF_SEAFILE_DIR],
            '--port', conf[CONF_SEAFILE_PORT],
            '--fileserver-port', conf[CONF_FILESERVER_PORT],
        ]

        if run_argv(argv) != 0:
            error('failed to init seafile configuration')

        info('done')

    seafile_ini = os.path.join(conf[CONF_CCNET_DIR], 'seafile.ini')
    with open(seafile_ini, 'w') as fp:
        fp.write(conf[CONF_SEAFILE_DIR])

####################
### <start> command
####################
def start_controller():
    argv = [
        'seafile-controller',
        '-c', conf[CONF_CCNET_DIR],
        '-d', conf[CONF_SEAFILE_DIR],
    ]

    info('Starting seafile-server...')
    if run_argv(argv) != 0:
        error('Failed to start seafile')

    # check again after several seconds
    time.sleep(10)

    if not is_running('seafile-controller'):
        error('Failed to start seafile')

def start_seahub_gunicorn():
    argv = [
        'gunicorn_django',
        '-c', conf[CONF_SEAHUB_CONF],
        '-b', '0.0.0.0:%s' % conf[CONF_SEAHUB_PORT],
    ]

    info('Starting seahub...')
    env = get_seahub_env()
    if run_argv(argv, cwd=conf[CONF_SEAHUB_DIR], env=env) != 0:
        error('Failed to start seahub')

    info('Seahub running on port %s' % conf[CONF_SEAHUB_PORT])

def start_seahub_fastcgi():
    info('Starting seahub in fastcgi mode...')
    argv = [
        PYTHON, 'manage.py', 'runfcgi',
        'host=127.0.0.1',
        'port=%(port)s',
        'pidfile=%(pidfile)s',
        'outlog=%(outlog)s',
        'errlog=%(errlog)s',
    ]

    cmdline = ' '.join(argv) % \
              dict(port=conf[CONF_SEAHUB_PORT],
                   pidfile=conf[CONF_SEAHUB_PIDFILE],
                   outlog=conf[CONF_SEAHUB_OUTLOG],
                   errlog=conf[CONF_SEAHUB_ERRLOG])

    env = get_seahub_env()

    if run(cmdline, cwd=conf[CONF_SEAHUB_DIR], env=env) != 0:
        error('Failed to start seahub in fastcgi mode')

    info('Seahub running on port %s (fastcgi)' % conf[CONF_SEAHUB_PORT])


def read_seafile_data_dir(ccnet_conf_dir):
    '''Read the location of seafile-data from seafile.ini, also consider the
    upgrade from older version which do not has the seafile.ini feature

    '''
    seafile_ini = os.path.join(ccnet_conf_dir, 'seafile.ini')
    if os.path.exists(seafile_ini):
        with open(seafile_ini, 'r') as fp:
            seafile_data_dir = fp.read().strip()
    else:
        # In previous seafile-admin, seafiled-data folder must be under
        # the top level directory, so we do not store the location of
        # seafile-data folder in seafile.ini
        seafile_data_dir = os.path.join(cwd, 'seafile-data')
        if os.path.exists(seafile_data_dir):
            with open(seafile_ini, 'w') as fp:
                fp.write(seafile_data_dir)

    return seafile_data_dir

def check_layout(args):
    def error_not_found(path):
        error('%s not found' % path)
    ccnet_conf_dir = os.path.join(cwd, 'ccnet')
    if not os.path.exists(ccnet_conf_dir):
        error_not_found(ccnet_conf_dir)

    ccnet_conf = os.path.join(ccnet_conf_dir, 'ccnet.conf')
    if not os.path.exists(ccnet_conf):
        error_not_found(ccnet_conf)

    seafile_data_dir = read_seafile_data_dir(ccnet_conf_dir)
    if not os.path.exists(seafile_data_dir):
        error_not_found(seafile_data_dir)

    seafile_conf = os.path.join(seafile_data_dir, 'seafile.conf')
    if not os.path.exists(seafile_conf):
        error_not_found(seafile_conf)

    runtime_dir = os.path.join(cwd, 'seafile-server', 'runtime')
    seahub_conf = os.path.join(runtime_dir, 'seahub.conf')
    if not os.path.exists(seahub_conf):
        error_not_found(seahub_conf)

    seahub_dir = os.path.join(cwd, 'seafile-server', 'seahub')
    if not os.path.exists(seahub_conf):
        error_not_found(seahub_dir)

    conf[CONF_CCNET_DIR]        = ccnet_conf_dir
    conf[CONF_SEAFILE_DIR]      = seafile_data_dir
    conf[CONF_SEAHUB_DIR]       = seahub_dir
    conf[CONF_SEAHUB_CONF]      = seahub_conf
    conf[CONF_SEAHUB_PIDFILE]   = os.path.join(runtime_dir, 'seahub.pid')
    conf[CONF_SEAHUB_OUTLOG]    = os.path.join(runtime_dir, 'access.log')
    conf[CONF_SEAHUB_ERRLOG]    = os.path.join(runtime_dir, 'error.log')

def check_config(args):
    check_layout(args)

    try:
        port = int(args.port)
    except ValueError:
        error('invalid port: %s' % args.port)
    else:
        if port <= 0 or port > 65535:
            error('invalid port: %s' % args.port)

    conf[CONF_SEAHUB_PORT]      = port

def check_directory_layout():
    seaf_server_dir = os.path.join(cwd, 'seafile-server')
    if not os.path.exists(seaf_server_dir):
        error('"seafile-server/" not found in current directory. \nPlease run seafile-admin in the correct directory.')

    seahub_dir = os.path.join(seaf_server_dir, 'seahub')
    if not os.path.exists(seahub_dir):
        error('"seafile-server/seahub/" not found. \nPlease download seahub first.')

    conf[CONF_SEAHUB_DIR] = seahub_dir

def setup_seafile(args):
    # avoid pylint "unused variable" warning
    dummy = args

    welcome()
    check_python_dependencies()
    config_ccnet_seafile()
    init_ccnet_seafile()
    init_seahub()

    print
    print '-----------------------------------------------------------------'
    print '-----------------------------------------------------------------'
    print 'Your seafile server configuration has been finished successfully.'
    print '-----------------------------------------------------------------'
    print '-----------------------------------------------------------------'
    print
    print 'To start/stop seafile server:'
    print
    print highlight('         $ cd %s' % cwd)
    print highlight('         $ %s { start | stop }' % SCRIPT_NAME)
    print
    print 'If you have any problem, refer to\n'
    print
    print ' Seafile server manual:      %s' % SERVER_MANUAL_HTTP
    print
    print ' Seafile discussion group:   %s' % SEAFILE_GOOGLE_GROUP
    print
    print ' Seafile website:            %s' % SEAFILE_WEBSITE
    print
    print 'for more information.'
    print

def check_necessary_files():
    files = [
        os.path.join(cwd, 'ccnet', 'ccnet.conf'),
        os.path.join(cwd, 'seafile-server', 'runtime', 'seahub.conf'),
        os.path.join(cwd, 'seahub.db'),
        os.path.join(cwd, 'seahub_settings.py'),
    ]

    for fpath in files:
        if not os.path.exists(fpath):
            error('%s not found' % fpath)

def start_seafile(args):
    '''start ccnet/seafile/seahub/fileserver'''
    if is_running('seafile-controller'):
        error(highlight('NOTE: Seafile is already running'))

    check_python_dependencies(silent=True)
    if args.fastcgi:
        check_python_module('flup', 'flup', silent=True)
    else:
        check_python_module('gunicorn', 'gunicorn', silent=True)

    check_necessary_files()

    check_config(args)

    start_controller()

    if args.port:
        try:
            port = int(args.port)
        except ValueError:
            error('invalid port: %s' % args.port)
        else:
            if port <= 0 or port > 65535:
                error('invalid port: %s' % args.port)

    if args.fastcgi:
        start_seahub_fastcgi()
    else:
        start_seahub_gunicorn()

    info('Done')

def stop_seafile(dummy):
    info('Stopping seafile server')
    pkill('seafile-controller')
    runtime_dir = os.path.join(cwd, 'seafile-server', 'runtime')
    pidfile = os.path.join(runtime_dir, 'seahub.pid')
    try:
        with open(pidfile, 'r') as fp:
            pid = fp.read().strip('\n ')
            if pid:
                kill(pid)
    except:
        pass

    info('done')

def reset_admin(args):
    '''reset seafile admin account'''
    check_layout(args)
    env = get_seahub_env()

    argv = [PYTHON, 'manage.py', 'createsuperuser']

    env = get_seahub_env()
    seahub_dir = conf[CONF_SEAHUB_DIR]
    run_argv(argv, cwd=seahub_dir, env=env)

def main():
    check_seafile_install()
    check_directory_layout()

    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(title='subcommands',
                                       description='')

    parser_setup = subparsers.add_parser('setup', help='setup the seafile server')
    parser_setup.set_defaults(func=setup_seafile)

    parser_start = subparsers.add_parser('start', help='start the seafile server')
    parser_start.set_defaults(func=start_seafile)

    parser_start.add_argument('--fastcgi', help='start seahub in fastcgi mode',
                              action='store_true')

    parser_start.add_argument('--port', help='start seahub in fastcgi mode',
                              default='8000')

    parser_stop = subparsers.add_parser('stop', help='stop the seafile server')
    parser_stop.set_defaults(func=stop_seafile)

    parser_reset_admin = subparsers.add_parser('reset-admin', help='reset seafile admin account')
    parser_reset_admin.set_defaults(func=reset_admin)

    parser_create_admin = subparsers.add_parser('create-admin', help='create seafile admin account')
    parser_create_admin.set_defaults(func=reset_admin)

    args = parser.parse_args()
    args.func(args)

if __name__ == '__main__':
    main()
