-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathseafile_mounter.py
145 lines (113 loc) · 4.32 KB
/
seafile_mounter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import flask
import os
import subprocess
from configparser import ConfigParser
from flask import request
import traceback
import signal
import argparse
app = flask.Flask(__name__)
app.config["DEBUG"] = True
__processes_by_user = dict()
__mount_dir = None
__data_dir = None
__default_drive_config = None
def __mkdir(d):
if not os.path.exists(d):
os.makedirs(d)
return True
return False
@app.route("/prepare/<username>")
def prepare(username):
global __data_dir
global __mount_dir
global __default_drive_config
token = request.args.get("token")
if token is None:
app.logger.error("No token for {}".format(username))
return "Missing token", 500
user_drive_mnt = os.path.join(__mount_dir, username)
# Unmount if the directory exists (ignore errors)
try:
if os.path.exists(user_drive_mnt):
unmount(username)
except Exception:
app.logger.exception("Ignoring unmount error for {}".format(username))
pass
try:
# Make directories to do the mounting
user_drive_data = os.path.join(__data_dir, username)
__mkdir(user_drive_data)
__mkdir(user_drive_mnt)
# Write the config for mounting the drive
user_drive_cfg = os.path.join(user_drive_data, "seadrive.conf")
config = ConfigParser()
config.read(__default_drive_config)
config['account']['username'] = username
config['account']['token'] = token
with open(user_drive_cfg, "w") as configfile:
config.write(configfile)
except Exception:
app.logger.exception("Error mounting for {}".format(username))
return {
"result": False,
"error": traceback.format_exc()
}, 500
return {"result": True}
@app.route("/mount/<username>")
def mount(username):
global __processes_by_user
global __data_dir
global __mount_dir
try:
user_drive_mnt = os.path.join(__mount_dir, username)
user_drive_data = os.path.join(__data_dir, username)
user_drive_cfg = os.path.join(user_drive_data, "seadrive.conf")
user_drive_data_folder = os.path.join(user_drive_data, "data")
# Do the mount (fuse)
app.logger.info("Starting the mount for {} in {}".format(username, user_drive_mnt))
drive_process = subprocess.Popen(" ".join([
"/usr/bin/seadrive", "-c", user_drive_cfg, "-f",
"-d", user_drive_data_folder, "-o", "uid=901325,gid=11860,allow_other,umask=002",
user_drive_mnt]), shell=True)
app.logger.info("Mount done for {} in {}".format(username, user_drive_mnt))
# Store the process to be cleared later
__processes_by_user[username] = drive_process
except Exception:
app.logger.exception("Error mounting for {}".format(username))
return {
"result": False,
"error": traceback.format_exc()
}, 500
return {"result": True}
@app.route("/unmount/<username>")
def unmount(username):
global __processes_by_user
# Unmount using fusermount
app.logger.info("Unmounting for {} using fusermount".format(username))
user_drive_mnt = os.path.join(__mount_dir, username)
subprocess.run(["fusermount", "-u", user_drive_mnt])
# If the process was started here, stop it now
if username in __processes_by_user:
app.logger.info("Stopping mount process for {}".format(username))
drive_process = __processes_by_user[username]
del __processes_by_user[username]
drive_process.send_signal(signal.SIGINT)
drive_process.wait()
del drive_process
return {"result": True}
parser = argparse.ArgumentParser(
description="REST service for mounting Seadrive for docker users")
parser.add_argument("-m", "--mountdir", required=True,
help="Directory to mount into")
parser.add_argument("-d", "--datadir", required=True,
help="Directory to store data in")
parser.add_argument("-c", "--config", required=True,
help="Default config file to fill in")
parser.add_argument("-p", "--port", required=False, default=5000,
help="Port to listen on")
args = parser.parse_args()
__mount_dir = args.mountdir
__data_dir = args.datadir
__default_drive_config = args.config
app.run(host="0.0.0.0", port=args.port)