forked from haiwen/seafile-docker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlauncher
executable file
·416 lines (349 loc) · 10.9 KB
/
launcher
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
#!/bin/bash
usage () {
echo "Usage: launcher COMMAND [--skip-prereqs] [--docker-args STRING]"
echo "Commands:"
echo " start: Start/initialize the container"
echo " stop: Stop a running container"
echo " restart: Restart the container"
echo " destroy: Stop and remove the container"
echo " enter: Open a shell to run commands inside the container"
echo " logs: View the Docker container logs"
echo " bootstrap: Bootstrap the container based on a template"
echo " rebuild: Rebuild the container (destroy old, bootstrap, start new)"
echo
echo "Options:"
echo " --skip-prereqs Don't check launcher prerequisites"
echo " --docker-args Extra arguments to pass when running docker"
exit 1
}
set -e
set -o pipefail
version=6.0.7
image=seafileltd/seafile:$version
local_image=local_seafile/server:latest
dockerdir=$(cd "$(dirname $0)"; pwd -P)
sharedir=$dockerdir/shared
installdir=/opt/seafile/seafile-server-$version
bootstrap_conf=$dockerdir/bootstrap/bootstrap.conf
version_stamp_file=$sharedir/seafile/seafile-data/current_version
cd $dockerdir
logdbg() {
if [[ $verbose == "true" ]]; then
loginfo "[debug] $1"
fi
}
loginfo() {
if [[ -t 1 ]]; then
>&2 printf "[$(date +'%Y-%m-%d %H:%M:%S')] \033[32m%s\033[m\n" "$1"
else
>&2 echo "[$(date +'%Y-%m-%d %H:%M:%S')] " "$1"
fi
}
install_docker() {
echo "---------------------------------------------------------------------------------"
echo "Docker is not installed, you will need to install Docker in order to run Launcher"
echo "See https://docs.docker.com/installation/"
echo "---------------------------------------------------------------------------------"
exit 1
}
err_and_quit () {
if [[ -t 1 ]]; then
>&2 printf "\n\n\033[33mError: %s\033[m\n\n" "$1"
else
>&2 echo "$1"
fi
exit 1
}
init_shared() {
mkdir -p $sharedir/{seafile,db}
mkdir -p $sharedir/logs/{seafile,var-log}
mkdir -p $sharedir/logs/var-log/nginx
touch $sharedir/logs/var-log/syslog
local bash_history=$sharedir/.bash_history
if [[ ! -e $bash_history ]]; then
touch $bash_history
fi
}
set_envs() {
envs=""
if [[ $verbose == "true" ]]; then
envs="$envs -e SEAFILE_DOCKER_VERBOSE=true"
fi
}
set_ports() {
ports=$(docker run $user_args --rm -it \
-v ${dockerdir}/scripts:/scripts \
-v ${dockerdir}/bootstrap:/bootstrap:ro \
$image \
/scripts/bootstrap.py --parse-ports)
}
set_bootstrap_volumes() {
local mounts
init_shared
mounts=(
$sharedir:/shared
$sharedir/logs/var-log:/var/log
$sharedir/db:/var/lib/mysql
$dockerdir/bootstrap:/bootstrap
$dockerdir/scripts:/scripts:ro
$dockerdir/templates:/templates:ro
$dockerdir/scripts/tmp/check_init_admin.py:$installdir/check_init_admin.py:ro
$sharedir/.bash_history:/root/.bash_history
)
volumes=""
local m
for m in ${mounts[*]}; do
volumes="$volumes -v $m"
done
}
set_volumes() {
local mounts
init_shared
mounts=(
$sharedir:/shared
$sharedir/logs/var-log:/var/log
$sharedir/db:/var/lib/mysql
$sharedir/.bash_history:/root/.bash_history
)
volumes=""
local m
for m in ${mounts[*]}; do
volumes="$volumes -v $m"
done
}
set_existing_container() {
existing=$(docker ps -a | awk '{ print $1, $(NF) }' | grep " seafile$" | awk '{ print $1 }' || true)
}
bootstrap() {
if [[ ! -e $bootstrap_conf ]]; then
err_and_quit "The file $bootstrap_conf doesn't exist. Have you run seafile-server-setup?"
fi
docker history $image >/dev/null 2>&1 || {
loginfo "Pulling Seafile server image $version, this may take a while."
docker pull $image
loginfo "Seafile server image $version pulled. Now bootstrapping the server ..."
}
# First initialize seafile server and letsencrypt
set_envs
set_bootstrap_volumes
set_ports
docker run $user_args --rm -it --name seafile-bootstrap -e SEAFILE_BOOTSRAP=1 $envs $volumes $ports $image /sbin/my_init $quiet -- /scripts/bootstrap.py
loginfo "Now building the local docker image."
docker build -f bootstrap/generated/Dockerfile -t local_seafile/server:latest . >/dev/null
loginfo "Image built."
}
start() {
existing=$(docker ps | awk '{ print $1, $(NF) }' | grep " seafile$" | awk '{ print $1 }' || true)
if [[ $existing != "" ]]; then
loginfo "Nothing to do, your container has already started!"
exit 0
fi
check_version_match
chmod 0700 $dockerdir/bootstrap $sharedir/seafile/conf
set_existing_container
if [[ $existing != "" ]]; then
loginfo "starting up existing container"
(
set -x
docker start seafile
)
exit 0
fi
set_envs
set_volumes
set_ports
local restart_policy attach_on_run
if [[ "${SUPERVISED}" = "true" ]]; then
restart_policy="--restart=no"
attach_on_run="-a stdout -a stderr"
else
attach_on_run="-d"
fi
loginfo "Starting up new seafile server container"
(
set -x
docker run $user_args $attach_on_run $restart_policy --name seafile -h seafile $envs $volumes $ports $local_image
)
}
ensure_container_running() {
set_existing_container
if [[ $existing == "" ]]; then
err_and_quit "seafile was not started !"
fi
}
stop() {
ensure_container_running
(
set -x
docker stop -t 10 seafile
)
}
enter() {
ensure_container_running
(
set -x
docker exec -it seafile /bin/bash
)
}
restart() {
stop
start
}
check_prereqs() {
if [[ $SKIP_PREREQS == "true" ]]; then
return 0
fi
# check docker
if ! which docker >/dev/null; then
install_docker
fi
# TODO: check git version
}
logs() {
ensure_container_running
(
set -x
docker logs --tail=20 -f seafile
)
}
destroy() {
(
set -x
docker stop -t 10 seafile || true
docker rm seafile
)
}
get_major_version() {
echo $1| awk -F . '{printf "%s.%s", $1, $2}'
}
check_version_match() {
local last_version last_major_version current_major_version
last_version=$(cat $version_stamp_file)
last_major_version=$(get_major_version $last_version)
current_major_version=$(get_major_version $version)
logdbg "Your version: ${last_version}, latest version: ${version}"
if [[ $last_major_version != "$current_major_version" ]]; then
loginfo "******* Major upgrade detected *******"
loginfo "You have $last_version, latest is $version"
loginfo "Please run './launcher rebuild' to upgrade"
exit 1
fi
}
check_upgrade() {
loginfo "Checking if there is major version upgrade"
local last_version last_major_version current_major_version
last_version=$(cat $version_stamp_file)
last_major_version=$(get_major_version $last_version)
current_major_version=$(get_major_version $version)
if [[ $last_major_version == "$current_major_version" ]]; then
return
else
loginfo "********************************"
loginfo "Major upgrade detected: You have $last_version, latest is $version"
loginfo "********************************"
# use_manual_upgrade=true
if [[ $use_manual_upgrade == "true" ]]; then
loginfo "Now you can run './launcher manual-upgrade' to do manual upgrade."
exit 0
else
loginfo "Going to launch the docker container for manual upgrade"
_launch_for_upgrade --auto
fi
fi
}
_launch_for_upgrade() {
local cmd
if [[ $1 == "--auto" ]]; then
cmd="/scripts/upgrade.py"
else
cmd="/bin/bash"
fi
set_envs
set_volumes
(
set -x
docker run $user_args \
-it --rm --name seafile-upgrade -h seafile \
$envs $volumes $local_image \
/sbin/my_init $quiet -- $cmd
)
}
rebuild() {
if [[ "$(git symbolic-ref --short HEAD)" == "master" ]]; then
loginfo "Ensuring launcher is up to date"
git remote update
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "@{u}")
BASE=$(git merge-base @ "@{u}")
if [[ $LOCAL = "$REMOTE" ]]; then
loginfo "Launcher is up-to-date"
elif [[ $LOCAL = "$BASE" ]]; then
loginfo "Updating Launcher"
git pull || (echo 'failed to update' && exit 1)
for (( i=${#BASH_ARGV[@]}-1,j=0; i>=0,j<${#BASH_ARGV[@]}; i--,j++ ))
do
args[$j]=${BASH_ARGV[$i]}
done
exec /bin/bash $0 "${args[@]}" # $@ is empty, because of shift at the beginning. Use BASH_ARGV instead.
elif [[ $REMOTE = "$BASE" ]]; then
loginfo "Your version of Launcher is ahead of origin"
else
loginfo "Launcher has diverged source, this is only expected in Dev mode"
fi
fi
set_existing_container
if [[ $existing != "" ]]; then
loginfo "Stopping old container"
(
set -x
docker stop -t 10 seafile
)
fi
bootstrap
loginfo "Rebuilt successfully."
if [[ $existing != "" ]]; then
loginfo "Removing old container"
(
set -x
docker rm seafile
)
fi
check_upgrade
start
loginfo "Your seafile server is now running."
exit 0
}
manual_upgrade() {
_launch_for_upgrade
loginfo "If you have manually upgraded the server, please update the version stamp by:"
loginfo
loginfo " echo $version | sudo tee $version_stamp_file"
loginfo " sudo ./launcher start"
loginfo
}
main() {
local action
while [[ $# -gt 0 ]]
do
case "$1" in
bootstrap|start|stop|restart|enter|destroy|logs|rebuild|manual-upgrade)
action=${1//-/_} ; shift 1 ;;
-h|--help) ( usage ; exit 1) ; shift 1 ;;
-v|--verbose) verbose=true ; shift 1 ;;
--skip-prereqs) SKIP_PREREQS=true ; shift 1 ;;
--docker-args) user_args=$2 ; shift 2 ;;
--manual-upgrade) use_manual_upgrade=true ; shift 1 ;;
*) err_and_quit "Argument error. Please see help." ;;
esac
done
# By default we suppress the verbose logs like "Running
# /etc/my_init.d/99_mysql_setup.sh". Use "./launcher -v <cmd>" to enable
# printing of these verbose logs.
quiet="--quiet"
if [[ $verbose == "true" ]]; then
quiet=""
fi
"$action"
}
check_prereqs
main "$@"