2013-02-03 11:05:20 +08:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
seaf-cli is command line interface for seafile client.
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
Subcommands:
|
2013-02-13 12:57:02 +08:00
|
|
|
init: create config files for seafile client
|
|
|
|
start: start and run seafile client as daemon
|
|
|
|
stop: stop seafile client
|
|
|
|
download: download a library from seafile server
|
|
|
|
sync: synchronize an existing folder with a library in
|
|
|
|
seafile server
|
|
|
|
desync: desynchronize a library with seafile server
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
|
|
|
init
|
|
|
|
----
|
2013-02-13 12:57:02 +08:00
|
|
|
Initialize seafile client. This command create sub-directories `seafile-data` and `seafile` under `parent-dir`.
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
usage: seaf-cli init -d <parent-dir>
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
start
|
|
|
|
-----
|
2013-02-13 12:57:02 +08:00
|
|
|
Start seafile client. This command start `ccnet` and `seaf-daemon`, `ccnet` is the network part of seafile client, `seaf-daemon` manages the files.
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
usage: seaf-cli start
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
stop
|
|
|
|
----
|
|
|
|
Stop seafile client.
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
usage: seaf-cli stop
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
clone
|
|
|
|
-----
|
2013-02-13 12:57:02 +08:00
|
|
|
clone a library from seafile server
|
|
|
|
|
|
|
|
usage: seaf-cli clone -r <library-id> -h <seahub-server-url> -d <parent-directory> -u <username> -p <password>
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
sync
|
|
|
|
----
|
2013-02-13 12:57:02 +08:00
|
|
|
Synchronize a library with an existing folder.
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
usage: seaf-cli sync -r <library-id> -h <seahub-server-url> -d <existing-folder> -u <username> -p <password>
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
desync
|
|
|
|
------
|
2013-02-13 12:57:02 +08:00
|
|
|
Desynchronize a library from seafile server
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
usage: seaf-cli desync -d <existing-folder>
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
import argparse
|
2013-02-13 12:57:02 +08:00
|
|
|
import os
|
|
|
|
import simplejson as json
|
2013-02-03 11:05:20 +08:00
|
|
|
import subprocess
|
2013-02-13 12:57:02 +08:00
|
|
|
import sys
|
2013-02-03 11:05:20 +08:00
|
|
|
import time
|
|
|
|
|
|
|
|
import ccnet
|
|
|
|
import seafile
|
|
|
|
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
DEFAULT_CONF_DIR = "%s/.ccnet" % os.environ['HOME']
|
|
|
|
|
|
|
|
seafile_datadir = None
|
|
|
|
seafile_worktree = None
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
# check python version
|
|
|
|
if sys.version_info.major == 3:
|
|
|
|
print 'Python 3 not support 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)
|
|
|
|
|
|
|
|
|
|
|
|
def _check_seafile():
|
|
|
|
''' Check ccnet and seafile have been installed '''
|
|
|
|
|
|
|
|
dirs = os.environ['PATH'].split(':')
|
|
|
|
def exist_in_path(prog):
|
|
|
|
''' Check whether 'prog' exists in system path '''
|
|
|
|
for d in dirs:
|
|
|
|
if d == '':
|
2013-02-13 12:57:02 +08:00
|
|
|
continue
|
|
|
|
path = os.path.join(d, prog)
|
|
|
|
if os.path.exists(path):
|
|
|
|
return True
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
progs = [ 'ccnet', 'ccnet-init', 'seaf-daemon' ]
|
|
|
|
|
|
|
|
for prog in progs:
|
|
|
|
if not exist_in_path(prog):
|
2013-02-13 12:57:02 +08:00
|
|
|
print "%s not found in PATH. Have you installed seafile?" % prog
|
2013-02-03 11:05:20 +08:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
def _config_valid(conf):
|
|
|
|
''' Check config file valid '''
|
|
|
|
|
|
|
|
if not os.path.exists(conf) or not os.path.isdir(conf):
|
2013-02-13 12:57:02 +08:00
|
|
|
print "%s not exists" % conf
|
2013-02-03 11:05:20 +08:00
|
|
|
return False
|
|
|
|
|
|
|
|
config_conf = conf + "/ccnet.conf"
|
|
|
|
seafile_ini = conf + "/seafile.ini"
|
2013-02-13 12:57:02 +08:00
|
|
|
if not os.path.exists(config_conf):
|
|
|
|
print "Can not load %s" % config_conf
|
|
|
|
return False
|
|
|
|
if not os.path.exists(seafile_ini):
|
|
|
|
print "Can not load %s" % seafile_ini
|
2013-02-03 11:05:20 +08:00
|
|
|
return False
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
with open(seafile_ini) as f:
|
|
|
|
for line in f:
|
|
|
|
global seafile_datadir, seafile_worktree
|
|
|
|
seafile_datadir = line.strip()
|
|
|
|
seafile_worktree = os.path.join(
|
|
|
|
os.path.dirname(seafile_datadir), "seafile")
|
|
|
|
break
|
|
|
|
|
|
|
|
if not seafile_datadir or not seafile_worktree:
|
|
|
|
print "Can not load seafile_datadir and seafile_worktree"
|
|
|
|
return False
|
2013-02-03 11:05:20 +08:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
def seaf_init(args):
|
|
|
|
''' initialize config files'''
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
ccnet_conf_dir = DEFAULT_CONF_DIR
|
|
|
|
if args.confdir:
|
|
|
|
ccnet_conf_dir = args.confdir
|
|
|
|
if args.dir:
|
|
|
|
seafile_path = args.dir
|
|
|
|
seafile_path = os.path.abspath(seafile_path)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
if os.path.exists(ccnet_conf_dir):
|
|
|
|
print "%s has existsed" % ccnet_conf_dir
|
2013-02-03 11:05:20 +08:00
|
|
|
sys.exit(0)
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
import socket
|
|
|
|
node_name = socket.gethostname()
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
cmd = [ "ccnet-init", "-c", ccnet_conf_dir, "-n", node_name ]
|
2013-02-03 11:05:20 +08:00
|
|
|
subprocess.call(cmd)
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
if not os.path.exists(seafile_path):
|
|
|
|
print "%s not exists" % seafile_path
|
|
|
|
sys.exit(0)
|
|
|
|
seafile_ini = ccnet_conf_dir + "/seafile.ini"
|
|
|
|
seafile_data = seafile_path + "/seafile-data"
|
2013-02-03 11:05:20 +08:00
|
|
|
fp = open(seafile_ini, 'w')
|
|
|
|
fp.write(seafile_data)
|
|
|
|
fp.close()
|
2013-02-13 12:57:02 +08:00
|
|
|
print "Writen seafile data directory %s to %s" % (seafile_data, seafile_ini)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
def seaf_start_all(args):
|
|
|
|
''' start ccnet and seafile daemon '''
|
|
|
|
|
|
|
|
seaf_start_ccnet(args)
|
|
|
|
# wait ccnet process
|
|
|
|
time.sleep(1)
|
|
|
|
seaf_start_seafile(args)
|
|
|
|
|
|
|
|
|
|
|
|
def seaf_start_ccnet(args):
|
|
|
|
''' start ccnet daemon '''
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
conf_dir = DEFAULT_CONF_DIR
|
|
|
|
if args.confdir:
|
|
|
|
conf_dir = args.confdir
|
|
|
|
conf_dir = os.path.abspath(conf_dir)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
if not _config_valid(conf_dir):
|
|
|
|
print "Config directory invalid"
|
2013-02-03 11:05:20 +08:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
print "starting ccnet daemon ..."
|
2013-02-13 12:57:02 +08:00
|
|
|
cmd = [ "ccnet", "--daemon", "-c", conf_dir ]
|
2013-02-03 11:05:20 +08:00
|
|
|
subprocess.call(cmd)
|
2013-02-13 12:57:02 +08:00
|
|
|
print "started ccnet daemon ..."
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
def seaf_start_seafile(args):
|
|
|
|
''' start seafile daemon '''
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
conf_dir = DEFAULT_CONF_DIR
|
|
|
|
if args.confdir:
|
|
|
|
conf_dir = args.confdir
|
|
|
|
conf_dir = os.path.abspath(conf_dir)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
if not _config_valid(conf_dir):
|
2013-02-03 11:05:20 +08:00
|
|
|
print "Config file invalid"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
print "starting seafile daemon ..."
|
2013-02-13 12:57:02 +08:00
|
|
|
cmd = [ "seaf-daemon", "--daemon", "-c", conf_dir, "-d", seafile_datadir,
|
|
|
|
"-w", seafile_worktree ]
|
2013-02-03 11:05:20 +08:00
|
|
|
subprocess.call(cmd)
|
2013-02-13 12:57:02 +08:00
|
|
|
print "started seafile daemon ..."
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
def seaf_download(args):
|
|
|
|
'''Download a library from seafile server '''
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
conf_dir = DEFAULT_CONF_DIR
|
|
|
|
if args.confdir:
|
|
|
|
conf_dir = args.confdir
|
|
|
|
conf_dir = os.path.abspath(conf_dir)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
if not _config_valid(conf_dir):
|
2013-02-03 11:05:20 +08:00
|
|
|
print "Config file invalid"
|
|
|
|
sys.exit(1)
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
repo = args.library
|
2013-02-03 11:05:20 +08:00
|
|
|
if not repo:
|
2013-02-13 12:57:02 +08:00
|
|
|
print "Library id need to be presented"
|
2013-02-03 11:05:20 +08:00
|
|
|
sys.exit(1)
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
url = args.server
|
2013-02-03 11:05:20 +08:00
|
|
|
if not url:
|
2013-02-13 12:57:02 +08:00
|
|
|
print "Seafile server url need to be presented"
|
2013-02-03 11:05:20 +08:00
|
|
|
sys.exit(1)
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
download_dir = seafile_worktree
|
|
|
|
if args.dir:
|
|
|
|
download_dir = os.path.abspath(args.dir)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
print "try to connect ..."
|
2013-02-13 12:57:02 +08:00
|
|
|
pool = ccnet.ClientPool(conf_dir)
|
2013-02-03 11:05:20 +08:00
|
|
|
ccnet_rpc = ccnet.CcnetRpcClient(pool, req_pool=True)
|
|
|
|
seafile_rpc = seafile.RpcClient(pool, req_pool=True)
|
|
|
|
|
|
|
|
username = args.name
|
|
|
|
if not username:
|
|
|
|
username = raw_input("Enter username: ")
|
|
|
|
password = args.password
|
|
|
|
if not password:
|
|
|
|
import getpass
|
2013-02-13 12:57:02 +08:00
|
|
|
password = getpass.getpass("Enter password for user %s " % username)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
# curl -d 'username=XXX&password=YYY' http://127.0.0.1:8000/api2/auth-token
|
|
|
|
cmd = [
|
2013-02-13 12:57:02 +08:00
|
|
|
"curl", "-k", "-d",
|
2013-02-03 11:05:20 +08:00
|
|
|
"username=%s&password=%s" % (username, password),
|
|
|
|
"%s/api2/auth-token/" % url
|
|
|
|
]
|
|
|
|
token_json = subprocess.check_output(cmd)
|
|
|
|
tmp = json.loads(token_json)
|
|
|
|
token = tmp['token']
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
cmd = "curl -k -H 'Authorization: Token %s' -H 'Accept: application/json; indent=4' %s/api2/repos/%s/download-info/" % (token, url, repo)
|
2013-02-03 11:05:20 +08:00
|
|
|
repo_info = os.popen(cmd).read()
|
2013-02-13 12:57:02 +08:00
|
|
|
# print repo_info
|
2013-02-03 11:05:20 +08:00
|
|
|
tmp = json.loads(repo_info)
|
|
|
|
encrypted = tmp['encrypted']
|
|
|
|
clone_token = tmp['token']
|
|
|
|
relay_id = tmp['relay_id']
|
|
|
|
relay_addr = tmp['relay_addr']
|
|
|
|
relay_port = tmp['relay_port']
|
|
|
|
email = tmp['email']
|
|
|
|
repo_name = tmp['repo_name']
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
print "starting to download ..."
|
|
|
|
print "Library %s will be downloaded to %s" % (repo, download_dir)
|
|
|
|
seafile_rpc.download(repo,
|
|
|
|
relay_id,
|
|
|
|
repo_name.encode('utf-8'),
|
|
|
|
download_dir.encode('utf-8'),
|
|
|
|
clone_token,
|
|
|
|
None, None,
|
|
|
|
relay_addr,
|
|
|
|
relay_port,
|
|
|
|
email)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
def seaf_sync(args):
|
2013-02-13 12:57:02 +08:00
|
|
|
''' synchronize a library from seafile server '''
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
conf_dir = DEFAULT_CONF_DIR
|
|
|
|
if args.confdir:
|
|
|
|
conf_dir = args.condir
|
|
|
|
conf_dir = os.path.abspath(conf_dir)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
if not _config_valid(conf_dir):
|
2013-02-03 11:05:20 +08:00
|
|
|
print "Config file invalid"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
repo = args.repo
|
|
|
|
if not repo:
|
|
|
|
print "Repo id need to be presented"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
os.environ["CCNET_CONF_DIR"] = config_path
|
|
|
|
from seaserv import CCNET_CONF_PATH
|
|
|
|
from seaserv import seafile_rpc
|
2013-02-13 12:57:02 +08:00
|
|
|
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
seafile_rpc.sync(repo, None)
|
|
|
|
|
|
|
|
|
|
|
|
def seaf_desync(args):
|
|
|
|
''' desynchronize a repo from seafile server '''
|
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
conf_dir = DEFAULT_CONF_DIR
|
|
|
|
if args.confdir:
|
|
|
|
conf_dir = args.confdir
|
|
|
|
conf_dir = os.path.abspath(conf_dir)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
2013-02-13 12:57:02 +08:00
|
|
|
if not _config_valid(conf_dir):
|
2013-02-03 11:05:20 +08:00
|
|
|
print "Config file invalid"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
repo = args.repo
|
|
|
|
if not repo:
|
|
|
|
print "Repo id need to be presented"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
os.environ["CCNET_CONF_DIR"] = config_path
|
|
|
|
from seaserv import CCNET_CONF_PATH
|
|
|
|
from seaserv import seafile_rpc
|
|
|
|
from seaserv import get_repos, get_repo, get_default_seafile_worktree
|
|
|
|
|
|
|
|
from pysearpc import SearpcError
|
|
|
|
|
|
|
|
pool = ccnet.ClientPool(CCNET_CONF_PATH)
|
|
|
|
ccnet_rpc = ccnet.CcnetRpcClient(pool, req_pool=True)
|
|
|
|
seafile_rpc = seafile.RpcClient(pool, req_pool=True)
|
|
|
|
|
|
|
|
seafile_rpc.remove_repo(repo)
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
''' Main entry '''
|
|
|
|
|
|
|
|
_check_seafile()
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
subparsers = parser.add_subparsers(title='subcommands', description='')
|
|
|
|
|
|
|
|
parser_init = subparsers.add_parser('init', help='Initialize config file')
|
2013-02-13 12:57:02 +08:00
|
|
|
parser_init.set_defaults(func=seaf_init)
|
|
|
|
parser_init.add_argument('-c', '--confdir', help='the config directory', type=str)
|
|
|
|
parser_init.add_argument('-d', '--dir', help='the parent directory to put seafile-data', type=str)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
parser_start = subparsers.add_parser('start',
|
|
|
|
help='Start ccnet and seafile daemon')
|
|
|
|
parser_start.set_defaults(func=seaf_start_all)
|
2013-02-13 12:57:02 +08:00
|
|
|
parser_start.add_argument('-c', '--confdir', help='the config directory', type=str)
|
|
|
|
|
|
|
|
parser_download = subparsers.add_parser('download',
|
|
|
|
help='Download a library from seafile server')
|
|
|
|
parser_download.set_defaults(func=seaf_download)
|
|
|
|
parser_download.add_argument('-c', '--confdir', help='the config directory', type=str)
|
|
|
|
parser_download.add_argument('-r', '--library', help='library id', type=str)
|
|
|
|
parser_download.add_argument('-s', '--server', help='URL for seafile server', type=str)
|
|
|
|
parser_download.add_argument('-d', '--dir', help='the directory to put the library', type=str)
|
|
|
|
parser_download.add_argument('-n', '--name', help='username', type=str)
|
|
|
|
parser_download.add_argument('-p', '--password', help='password', type=str)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
parser_sync = subparsers.add_parser('sync',
|
2013-02-13 12:57:02 +08:00
|
|
|
help='Sync a library with an existing foler')
|
2013-02-03 11:05:20 +08:00
|
|
|
parser_sync.set_defaults(func=seaf_sync)
|
2013-02-13 12:57:02 +08:00
|
|
|
parser_sync.add_argument('-c', '--confdir', help='the config directory', type=str)
|
|
|
|
parser_sync.add_argument('-r', '--library', help='library id', type=str)
|
|
|
|
parser_sync.add_argument('-s', '--server', help='URL for seafile server', type=str)
|
|
|
|
parser_sync.add_argument('-n', '--name', help='username', type=str)
|
|
|
|
parser_sync.add_argument('-p', '--password', help='password', type=str)
|
|
|
|
parser_sync.add_argument('-d', '--folder', help='the existing local folder', type=str)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
parser_desync = subparsers.add_parser('desync',
|
2013-02-13 12:57:02 +08:00
|
|
|
help='Desync a library with seafile server')
|
2013-02-03 11:05:20 +08:00
|
|
|
parser_desync.set_defaults(func=seaf_desync)
|
2013-02-13 12:57:02 +08:00
|
|
|
parser_desync.add_argument('-c', '--confdir', help='the config directory', type=str)
|
|
|
|
parser_desync.add_argument('-d', '--folder', help='the local folder', type=str)
|
2013-02-03 11:05:20 +08:00
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
args.func(args)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|