Merge branch '3219-further-docker-improvements'
[arvados.git] / docker / arvdock
1 #!/bin/bash
2
3 ENABLE_SSH=false
4 DOCKER=`which docker.io`
5
6 if [[ "$DOCKER" == "" ]]; then
7     DOCKER=`which docker`
8 fi
9
10 function usage {
11     echo >&2
12     echo >&2 "usage: $0 (start|stop|restart|test) [options]"
13     echo >&2
14     echo >&2 "$0 start/stop/restart options:"
15     echo >&2 "  -d [port], --doc[=port]        Documentation server (default port 9898)"
16     echo >&2 "  -w [port], --workbench[=port]  Workbench server (default port 9899)"
17     echo >&2 "  -s [port], --sso[=port]        SSO server (default port 9901)"
18     echo >&2 "  -a [port], --api[=port]        API server (default port 9900)"
19     echo >&2 "  -k, --keep                     Keep servers"
20     echo >&2 "  --ssh                          Enable SSH access to server containers"
21     echo >&2 "  -h, --help                     Display this help and exit"
22     echo >&2
23     echo >&2 "  If no options are given, the action is applied to all servers."
24     echo >&2
25     echo >&2 "$0 test [testname] [testname] ..."
26     echo >&2 "  By default, all tests are run."
27 }
28
29 function ip_address {
30     local container=$1
31     echo `$DOCKER inspect $container  |grep IPAddress |cut -f4 -d\"`
32 }
33
34 function start_container {
35     local args="-d -i -t"
36     if [[ "$1" != '' ]]; then
37       local port="$1"
38       args="$args -p $port"
39     fi
40     if [[ "$2" != '' ]]; then
41       local name="$2"
42       args="$args --name $name"
43     fi
44     if [[ "$3" != '' ]]; then
45       local volume="$3"
46       args="$args -v $volume"
47     fi
48     if [[ "$4" != '' ]]; then
49       local link="$4"
50       args="$args --link $link"
51     fi
52     local image=$5
53
54     if $ENABLE_SSH
55     then
56       args="$args -e ENABLE_SSH=$ENABLE_SSH"
57     fi
58
59     `$DOCKER ps |grep -P "$name[^/]" -q`
60     if [[ "$?" == "0" ]]; then
61       echo "You have a running container with name $name -- skipping."
62       return
63     fi
64
65     # Remove any existing container by this name.
66     $DOCKER rm "$name" 2>/dev/null
67
68     echo "Starting container:"
69     echo "  $DOCKER run $args $image"
70     container=`$DOCKER run $args $image`
71     if [[ "$?" != "0" ]]; then
72       echo "Unable to start container"
73       exit 1
74     fi
75     if $ENABLE_SSH
76     then
77       ip=$(ip_address $container )
78       echo
79       echo "You can ssh into the container with:"
80       echo
81       echo "    ssh root@$ip"
82       echo
83     fi
84
85     if [[ "$name" == "doc_server" ]]; then
86       echo
87       echo "*****************************************************************"
88       echo "You can access the Arvados documentation at http://localhost:${port%:*}"
89       echo "*****************************************************************"
90       echo
91     fi
92
93     if [[ "$name" == "workbench_server" ]]; then
94       echo
95       echo "*****************************************************************"
96       echo "You can access the Arvados workbench at http://localhost:${port%:*}"
97       echo "*****************************************************************"
98       echo
99    fi
100
101
102 }
103
104 declare -a keep_volumes
105
106 # Initialize the global `keep_volumes' array. If any keep volumes
107 # already appear to exist (mounted volumes with a top-level "keep"
108 # directory), use them; create temporary volumes if necessary.
109 #
110 function make_keep_volumes () {
111     # Mount a keep volume if we don't already have one
112     for mountpoint in $(cut -d ' ' -f 2 /proc/mounts); do
113       if [[ -d "$mountpoint/keep" && "$mountpoint" != "/" ]]; then
114         keep_volumes+=($mountpoint)
115       fi
116     done
117
118     # Create any keep volumes that do not yet exist.
119     while [ ${#keep_volumes[*]} -lt 2 ]
120     do
121         new_keep=$(mktemp -d)
122         echo >&2 "mounting 512M tmpfs keep volume in $new_keep"
123         sudo mount -t tmpfs -o size=512M tmpfs $new_keep
124         mkdir $new_keep/keep
125         keep_volumes+=($new_keep)
126     done
127 }
128
129 function do_start {
130     local start_doc=false
131     local start_sso=false
132     local start_api=false
133     local start_workbench=false
134     local start_keep=false
135
136     # NOTE: This requires GNU getopt (part of the util-linux package on Debian-based distros).
137     local TEMP=`getopt -o d::s::a::w::kh \
138                   --long doc::,sso::,api::,workbench::,keep,help,ssh \
139                   -n "$0" -- "$@"`
140
141     if [ $? != 0 ] ; then echo "Use -h for help"; exit 1 ; fi
142
143     # Note the quotes around `$TEMP': they are essential!
144     eval set -- "$TEMP"
145
146     while [ $# -ge 1 ]
147     do
148         case $1 in
149             -d | --doc)
150                 case "$2" in
151                     "") start_doc=9898; shift 2 ;;
152                     *)  start_doc=$2; shift 2 ;;
153                 esac
154                 ;;
155             -s | --sso)
156                 case "$2" in
157                     "") start_sso=9901; shift 2 ;;
158                     *)  start_sso=$2; shift 2 ;;
159                 esac
160                 ;;
161             -a | --api)
162                 case "$2" in
163                     "") start_api=9900; shift 2 ;;
164                     *)  start_api=$2; shift 2 ;;
165                 esac
166                 ;;
167             -w | --workbench)
168                 case "$2" in
169                     "") start_workbench=9899; shift 2 ;;
170                     *)  start_workbench=$2; shift 2 ;;
171                 esac
172                 ;;
173             -k | --keep)
174                 start_keep=true
175                 shift
176                 ;;
177             --ssh)
178                 # ENABLE_SSH is a global variable
179                 ENABLE_SSH=true
180                 shift
181                 ;;
182             --)
183                 shift
184                 break
185                 ;;
186             *)
187                 usage
188                 exit 1
189                 ;;
190         esac
191     done
192
193     # If no options were selected, then start all servers.
194     if [[ $start_doc == false &&
195           $start_sso == false &&
196           $start_api == false &&
197           $start_workbench == false &&
198           $start_keep == false ]]
199     then
200         start_doc=9898
201         start_sso=9901
202         start_api=9900
203         start_workbench=9899
204         start_keep=true
205     fi
206
207     if [[ $start_sso != false ]]
208     then
209         start_container "$start_sso:443" "sso_server" '' '' "arvados/sso"
210     fi
211
212     if [[ $start_api != false ]]
213     then
214         start_container "$start_api:443" "api_server" '' "sso_server:sso" "arvados/api"
215     fi
216
217     if [[ $start_keep != false ]]
218     then
219         # create `keep_volumes' array with a list of keep mount points
220         # remove any stale metadata from those volumes before starting them
221         make_keep_volumes
222         for v in ${keep_volumes[*]}
223         do
224             [ -f $v/keep/.metadata.yml ] && sudo rm $v/keep/.metadata.yml
225         done
226         start_container "25107:25107" "keep_server_0" \
227             "${keep_volumes[0]}:/dev/keep-0" \
228             "api_server:api" \
229             "arvados/keep"
230         start_container "25108:25107" "keep_server_1" \
231             "${keep_volumes[1]}:/dev/keep-0" \
232             "api_server:api" \
233             "arvados/keep"
234     fi
235
236     if [[ $start_doc != false ]]
237     then
238         start_container "$start_doc:80" "doc_server" '' '' "arvados/doc"
239     fi
240
241     if [[ $start_workbench != false ]]
242     then
243         start_container "$start_workbench:80" "workbench_server" '' "api_server:api" "arvados/workbench"
244     fi
245
246     if [ -d $HOME/.config/arvados ] || mkdir -p $HOME/.config/arvados
247     then
248         cat >$HOME/.config/arvados/settings.conf <<EOF
249 ARVADOS_API_HOST=$(ip_address "api_server")
250 ARVADOS_API_HOST_INSECURE=yes
251 ARVADOS_API_TOKEN=$(cat api/generated/superuser_token)
252 EOF
253     fi
254
255 }
256
257 function do_stop {
258     local stop_doc=""
259     local stop_sso=""
260     local stop_api=""
261     local stop_workbench=""
262     local stop_keep=""
263
264     # NOTE: This requires GNU getopt (part of the util-linux package on Debian-based distros).
265     local TEMP=`getopt -o d::s::a::w::kh \
266                   --long doc::,sso::,api::,workbench::,keep,help,ssh \
267                   -n "$0" -- "$@"`
268
269     if [ $? != 0 ] ; then echo "Use -h for help"; exit 1 ; fi
270
271     # Note the quotes around `$TEMP': they are essential!
272     eval set -- "$TEMP"
273
274     while [ $# -ge 1 ]
275     do
276         case $1 in
277             -d | --doc)
278                 stop_doc=doc_server ; shift 2 ;;
279             -s | --sso)
280                 stop_sso=sso_server ; shift 2 ;;
281             -a | --api)
282                 stop_api=api_server ; shift 2 ;;
283             -w | --workbench)
284                 stop_workbench=workbench_server ; shift 2 ;;
285             -k | --keep )
286                 stop_keep="keep_server_0 keep_server_1" ; shift ;;
287             --ssh)
288                 shift
289                 ;;
290             --)
291                 shift
292                 break
293                 ;;
294             *)
295                 usage
296                 exit 1
297                 ;;
298         esac
299     done
300
301     # If no options were selected, then stop all servers.
302     if [[ $stop_doc == "" &&
303           $stop_sso == "" &&
304           $stop_api == "" &&
305           $stop_workbench == "" &&
306           $stop_keep == "" ]]
307     then
308         stop_doc=doc_server
309         stop_sso=sso_server
310         stop_api=api_server
311         stop_workbench=workbench_server
312         stop_keep="keep_server_0 keep_server_1"
313     fi
314
315     $DOCKER stop $stop_doc $stop_sso $stop_api $stop_workbench $stop_keep \
316         2>/dev/null
317 }
318
319 function do_test {
320     local alltests
321     if [ $# -lt 1 ]
322     then
323         alltests="python-sdk api"
324     else
325         alltests="$@"
326     fi
327
328     for testname in $alltests
329     do
330         echo "testing $testname..."
331         case $testname in
332             python-sdk)
333                 do_start --api --keep --sso
334                 export ARVADOS_API_HOST=$(ip_address "api_server")
335                 export ARVADOS_API_HOST_INSECURE=yes
336                 export ARVADOS_API_TOKEN=$(cat api/generated/superuser_token)
337                 python -m unittest discover ../sdk/python
338                 ;;
339             api)
340                 $DOCKER run -t -i arvados/api \
341                     /usr/src/arvados/services/api/script/rake_test.sh
342                 ;;
343             *)
344                 echo >&2 "unknown test $testname"
345                 ;;
346         esac
347     done
348 }
349
350 if [ $# -lt 1 ]
351 then
352   usage
353   exit 1
354 fi
355
356 case $1 in
357     start)
358         shift
359         do_start $@
360         ;;
361     stop)
362         shift
363         do_stop $@
364         ;;
365     restart)
366         shift
367         do_stop $@
368         do_start $@
369         ;;
370     test)
371         shift
372         do_test $@
373         ;;
374     *)
375         usage
376         exit 1
377         ;;
378 esac